qtdemux: fix framerate calculation for fragmented format
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 /**
30  * SECTION:element-qtdemux
31  *
32  * Demuxes a .mov file into raw or compressed audio and/or video streams.
33  *
34  * This element supports both push and pull-based scheduling, depending on the
35  * capabilities of the upstream elements.
36  *
37  * <refsect2>
38  * <title>Example launch line</title>
39  * |[
40  * 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
41  * ]| Play (parse and decode) a .mov file and try to output it to
42  * an automatically detected soundcard and videosink. If the MOV file contains
43  * compressed audio or video data, this will only work if you have the
44  * right decoder elements/plugins installed.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include "gst/gst-i18n-plugin.h"
53
54 #include <glib/gprintf.h>
55 #include <gst/tag/tag.h>
56 #include <gst/audio/audio.h>
57 #include <gst/video/video.h>
58
59 #include "qtatomparser.h"
60 #include "qtdemux_types.h"
61 #include "qtdemux_dump.h"
62 #include "fourcc.h"
63 #include "descriptors.h"
64 #include "qtdemux_lang.h"
65 #include "qtdemux.h"
66 #include "qtpalette.h"
67
68 #include "gst/riff/riff-media.h"
69 #include "gst/riff/riff-read.h"
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
97
98 GST_DEBUG_CATEGORY (qtdemux_debug);
99
100 /*typedef struct _QtNode QtNode; */
101 typedef struct _QtDemuxSegment QtDemuxSegment;
102 typedef struct _QtDemuxSample QtDemuxSample;
103
104 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
105
106 /*struct _QtNode
107 {
108   guint32 type;
109   guint8 *data;
110   gint len;
111 };*/
112
113 struct _QtDemuxSample
114 {
115   guint32 size;
116   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
117   guint64 offset;
118   guint64 timestamp;            /* DTS In mov time */
119   guint32 duration;             /* In mov time */
120   gboolean keyframe;            /* TRUE when this packet is a keyframe */
121 };
122
123 /* Macros for converting to/from timescale */
124 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
125 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
126
127 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
128 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
129
130 /* timestamp is the DTS */
131 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
132 /* timestamp + offset is the PTS */
133 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 struct _QtDemuxStream
221 {
222   GstPad *pad;
223
224   /* stream type */
225   guint32 subtype;
226   GstCaps *caps;
227   guint32 fourcc;
228   gboolean sparse;
229
230   gboolean new_caps;
231   gboolean new_stream;          /* signals that a stream_start is required */
232   gboolean on_keyframe;         /* if this stream last pushed buffer was a
233                                  * keyframe. This is important to identify
234                                  * where to stop pushing buffers after a
235                                  * segment stop time */
236
237   /* if the stream has a redirect URI in its headers, we store it here */
238   gchar *redirect_uri;
239
240   /* track id */
241   guint track_id;
242
243   /* duration/scale */
244   guint64 duration;             /* in timescale */
245   guint32 timescale;
246
247   /* language */
248   gchar lang_id[4];             /* ISO 639-2T language code */
249
250   /* our samples */
251   guint32 n_samples;
252   QtDemuxSample *samples;
253   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
254   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
255                                    the framerate, in timescale units */
256   guint32 n_samples_moof;       /* sample count in a moof */
257   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
258                                  * the framerate of fragmented format stream */
259   guint32 offset_in_sample;
260   guint32 max_buffer_size;
261
262   /* if we use chunks or samples */
263   gboolean sampled;
264   guint padding;
265
266   /* video info */
267   gint width;
268   gint height;
269   /* aspect ratio */
270   gint display_width;
271   gint display_height;
272   gint par_w;
273   gint par_h;
274   /* Numerator/denominator framerate */
275   gint fps_n;
276   gint fps_d;
277   guint16 bits_per_sample;
278   guint16 color_table_id;
279   GstMemory *rgb8_palette;
280
281   /* audio info */
282   gdouble rate;
283   gint n_channels;
284   guint samples_per_packet;
285   guint samples_per_frame;
286   guint bytes_per_packet;
287   guint bytes_per_sample;
288   guint bytes_per_frame;
289   guint compression;
290
291   /* allocation */
292   gboolean use_allocator;
293   GstAllocator *allocator;
294   GstAllocationParams params;
295
296   /* when a discontinuity is pending */
297   gboolean discont;
298
299   /* list of buffers to push first */
300   GSList *buffers;
301
302   /* if we need to clip this buffer. This is only needed for uncompressed
303    * data */
304   gboolean need_clip;
305
306   /* buffer needs some custom processing, e.g. subtitles */
307   gboolean need_process;
308
309   /* current position */
310   guint32 segment_index;
311   guint32 sample_index;
312   GstClockTime time_position;   /* in gst time */
313   guint64 accumulated_base;
314
315   /* the Gst segment we are processing out, used for clipping */
316   GstSegment segment;
317   guint32 segment_seqnum;       /* segment event seqnum obtained from seek */
318
319   /* quicktime segments */
320   guint32 n_segments;
321   QtDemuxSegment *segments;
322   gboolean dummy_segment;
323   guint32 from_sample;
324   guint32 to_sample;
325
326   gboolean sent_eos;
327   GstTagList *pending_tags;
328   gboolean send_global_tags;
329
330   GstEvent *pending_event;
331
332   GstByteReader stco;
333   GstByteReader stsz;
334   GstByteReader stsc;
335   GstByteReader stts;
336   GstByteReader stss;
337   GstByteReader stps;
338   GstByteReader ctts;
339
340   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
341   gint64 stbl_index;
342   /* stco */
343   guint co_size;
344   GstByteReader co_chunk;
345   guint32 first_chunk;
346   guint32 current_chunk;
347   guint32 last_chunk;
348   guint32 samples_per_chunk;
349   guint32 stco_sample_index;
350   /* stsz */
351   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
352   /* stsc */
353   guint32 stsc_index;
354   guint32 n_samples_per_chunk;
355   guint32 stsc_chunk_index;
356   guint32 stsc_sample_index;
357   guint64 chunk_offset;
358   /* stts */
359   guint32 stts_index;
360   guint32 stts_samples;
361   guint32 n_sample_times;
362   guint32 stts_sample_index;
363   guint64 stts_time;
364   guint32 stts_duration;
365   /* stss */
366   gboolean stss_present;
367   guint32 n_sample_syncs;
368   guint32 stss_index;
369   /* stps */
370   gboolean stps_present;
371   guint32 n_sample_partial_syncs;
372   guint32 stps_index;
373   QtDemuxRandomAccessEntry *ra_entries;
374   guint n_ra_entries;
375
376   const QtDemuxRandomAccessEntry *pending_seek;
377
378   /* ctts */
379   gboolean ctts_present;
380   guint32 n_composition_times;
381   guint32 ctts_index;
382   guint32 ctts_sample_index;
383   guint32 ctts_count;
384   gint32 ctts_soffset;
385
386   /* cslg */
387   guint32 cslg_shift;
388
389   /* fragmented */
390   gboolean parsed_trex;
391   guint32 def_sample_duration;
392   guint32 def_sample_size;
393   guint32 def_sample_flags;
394
395   gboolean disabled;
396
397   /* stereoscopic video streams */
398   GstVideoMultiviewMode multiview_mode;
399   GstVideoMultiviewFlags multiview_flags;
400
401   /* protected streams */
402   gboolean protected;
403   guint32 protection_scheme_type;
404   guint32 protection_scheme_version;
405   gpointer protection_scheme_info;      /* specific to the protection scheme */
406   GQueue protection_scheme_event_queue;
407 };
408
409 /* Contains properties and cryptographic info for a set of samples from a
410  * track protected using Common Encryption (cenc) */
411 struct _QtDemuxCencSampleSetInfo
412 {
413   GstStructure *default_properties;
414
415   /* @crypto_info holds one GstStructure per sample */
416   GPtrArray *crypto_info;
417 };
418
419 enum QtDemuxState
420 {
421   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
422   QTDEMUX_STATE_HEADER,         /* Parsing the header */
423   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
424   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
425 };
426
427 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
428 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
429     guint32 fourcc, GstByteReader * parser);
430 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
431 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
432     guint32 fourcc, GstByteReader * parser);
433
434 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
435
436 static GstStaticPadTemplate gst_qtdemux_sink_template =
437     GST_STATIC_PAD_TEMPLATE ("sink",
438     GST_PAD_SINK,
439     GST_PAD_ALWAYS,
440     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
441         "application/x-3gp")
442     );
443
444 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
445 GST_STATIC_PAD_TEMPLATE ("video_%u",
446     GST_PAD_SRC,
447     GST_PAD_SOMETIMES,
448     GST_STATIC_CAPS_ANY);
449
450 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
451 GST_STATIC_PAD_TEMPLATE ("audio_%u",
452     GST_PAD_SRC,
453     GST_PAD_SOMETIMES,
454     GST_STATIC_CAPS_ANY);
455
456 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
457 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
458     GST_PAD_SRC,
459     GST_PAD_SOMETIMES,
460     GST_STATIC_CAPS_ANY);
461
462 #define gst_qtdemux_parent_class parent_class
463 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
464
465 static void gst_qtdemux_dispose (GObject * object);
466
467 static guint32
468 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
469     GstClockTime media_time);
470 static guint32
471 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
472     QtDemuxStream * str, gint64 media_offset);
473
474 #if 0
475 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
476 static GstIndex *gst_qtdemux_get_index (GstElement * element);
477 #endif
478 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
479     GstStateChange transition);
480 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
481 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
482     GstObject * parent, GstPadMode mode, gboolean active);
483
484 static void gst_qtdemux_loop (GstPad * pad);
485 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
486     GstBuffer * inbuf);
487 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
488     GstEvent * event);
489 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
490 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
491     QtDemuxStream * stream);
492 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
493     gboolean force);
494
495 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
496     const guint8 * buffer, guint length);
497 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
498     const guint8 * buffer, guint length);
499 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
500 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
501     GNode * udta);
502
503 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
504     QtDemuxStream * stream, GNode * esds, GstTagList * list);
505 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
506     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
507     gchar ** codec_name);
508 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
509     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
510     gchar ** codec_name);
511 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
512     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
513     gchar ** codec_name);
514 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
515     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
516     gchar ** codec_name);
517
518 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
519     QtDemuxStream * stream, guint32 n);
520 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
521 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
522     QtDemuxStream * stream);
523 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
524     QtDemuxStream * stream);
525 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
526 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
527 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
528     QtDemuxStream * stream);
529
530 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
531 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
532
533 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
534     const gchar * id);
535
536 static void
537 gst_qtdemux_class_init (GstQTDemuxClass * klass)
538 {
539   GObjectClass *gobject_class;
540   GstElementClass *gstelement_class;
541
542   gobject_class = (GObjectClass *) klass;
543   gstelement_class = (GstElementClass *) klass;
544
545   parent_class = g_type_class_peek_parent (klass);
546
547   gobject_class->dispose = gst_qtdemux_dispose;
548
549   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
550 #if 0
551   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
552   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
553 #endif
554
555   gst_tag_register_musicbrainz_tags ();
556
557   gst_element_class_add_pad_template (gstelement_class,
558       gst_static_pad_template_get (&gst_qtdemux_sink_template));
559   gst_element_class_add_pad_template (gstelement_class,
560       gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
561   gst_element_class_add_pad_template (gstelement_class,
562       gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
563   gst_element_class_add_pad_template (gstelement_class,
564       gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
565   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
566       "Codec/Demuxer",
567       "Demultiplex a QuickTime file into audio and video streams",
568       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
569
570   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
571
572 }
573
574 static void
575 gst_qtdemux_init (GstQTDemux * qtdemux)
576 {
577   qtdemux->sinkpad =
578       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
579   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
580   gst_pad_set_activatemode_function (qtdemux->sinkpad,
581       qtdemux_sink_activate_mode);
582   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
583   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
584   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
585
586   qtdemux->state = QTDEMUX_STATE_INITIAL;
587   qtdemux->pullbased = FALSE;
588   qtdemux->posted_redirect = FALSE;
589   qtdemux->pending_configure = FALSE;
590   qtdemux->neededbytes = 16;
591   qtdemux->todrop = 0;
592   qtdemux->adapter = gst_adapter_new ();
593   qtdemux->offset = 0;
594   qtdemux->first_mdat = -1;
595   qtdemux->got_moov = FALSE;
596   qtdemux->mdatoffset = -1;
597   qtdemux->mdatbuffer = NULL;
598   qtdemux->restoredata_buffer = NULL;
599   qtdemux->restoredata_offset = -1;
600   qtdemux->fragment_start = -1;
601   qtdemux->fragment_start_offset = -1;
602   qtdemux->media_caps = NULL;
603   qtdemux->exposed = FALSE;
604   qtdemux->mss_mode = FALSE;
605   qtdemux->pending_newsegment = NULL;
606   qtdemux->upstream_format_is_time = FALSE;
607   qtdemux->have_group_id = FALSE;
608   qtdemux->group_id = G_MAXUINT;
609   qtdemux->cenc_aux_info_offset = 0;
610   qtdemux->cenc_aux_info_sizes = NULL;
611   qtdemux->cenc_aux_sample_count = 0;
612   qtdemux->protection_system_ids = NULL;
613   g_queue_init (&qtdemux->protection_event_queue);
614   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
615   qtdemux->flowcombiner = gst_flow_combiner_new ();
616
617   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
618 }
619
620 static void
621 gst_qtdemux_dispose (GObject * object)
622 {
623   GstQTDemux *qtdemux = GST_QTDEMUX (object);
624
625   if (qtdemux->adapter) {
626     g_object_unref (G_OBJECT (qtdemux->adapter));
627     qtdemux->adapter = NULL;
628   }
629   gst_flow_combiner_free (qtdemux->flowcombiner);
630   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
631       NULL);
632   g_queue_clear (&qtdemux->protection_event_queue);
633
634   g_free (qtdemux->cenc_aux_info_sizes);
635   qtdemux->cenc_aux_info_sizes = NULL;
636
637   G_OBJECT_CLASS (parent_class)->dispose (object);
638 }
639
640 static void
641 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
642 {
643   if (qtdemux->posted_redirect) {
644     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
645         (_("This file contains no playable streams.")),
646         ("no known streams found, a redirect message has been posted"));
647   } else {
648     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
649         (_("This file contains no playable streams.")),
650         ("no known streams found"));
651   }
652 }
653
654 static GstBuffer *
655 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
656 {
657   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
658       mem, size, 0, size, mem, free_func);
659 }
660
661 static GstFlowReturn
662 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
663     GstBuffer ** buf)
664 {
665   GstFlowReturn flow;
666   GstMapInfo map;
667   gsize bsize;
668
669   if (G_UNLIKELY (size == 0)) {
670     GstFlowReturn ret;
671     GstBuffer *tmp = NULL;
672
673     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
674     if (ret != GST_FLOW_OK)
675       return ret;
676
677     gst_buffer_map (tmp, &map, GST_MAP_READ);
678     size = QT_UINT32 (map.data);
679     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
680
681     gst_buffer_unmap (tmp, &map);
682     gst_buffer_unref (tmp);
683   }
684
685   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
686   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
687     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
688       /* we're pulling header but already got most interesting bits,
689        * so never mind the rest (e.g. tags) (that much) */
690       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
691           size);
692       return GST_FLOW_EOS;
693     } else {
694       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
695           (_("This file is invalid and cannot be played.")),
696           ("atom has bogus size %" G_GUINT64_FORMAT, size));
697       return GST_FLOW_ERROR;
698     }
699   }
700
701   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
702
703   if (G_UNLIKELY (flow != GST_FLOW_OK))
704     return flow;
705
706   bsize = gst_buffer_get_size (*buf);
707   /* Catch short reads - we don't want any partial atoms */
708   if (G_UNLIKELY (bsize < size)) {
709     GST_WARNING_OBJECT (qtdemux,
710         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
711     gst_buffer_unref (*buf);
712     *buf = NULL;
713     return GST_FLOW_EOS;
714   }
715
716   return flow;
717 }
718
719 #if 1
720 static gboolean
721 gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
722     GstFormat dest_format, gint64 * dest_value)
723 {
724   gboolean res = TRUE;
725   QtDemuxStream *stream = gst_pad_get_element_private (pad);
726   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
727   gint32 index;
728
729   if (stream->subtype != FOURCC_vide) {
730     res = FALSE;
731     goto done;
732   }
733
734   switch (src_format) {
735     case GST_FORMAT_TIME:
736       switch (dest_format) {
737         case GST_FORMAT_BYTES:{
738           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
739           if (-1 == index)
740             return FALSE;
741
742           *dest_value = stream->samples[index].offset;
743
744           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
745               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
746               GST_TIME_ARGS (src_value), *dest_value);
747           break;
748         }
749         default:
750           res = FALSE;
751           break;
752       }
753       break;
754     case GST_FORMAT_BYTES:
755       switch (dest_format) {
756         case GST_FORMAT_TIME:{
757           index =
758               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
759               stream, src_value);
760
761           if (-1 == index)
762             return FALSE;
763
764           *dest_value =
765               QTSTREAMTIME_TO_GSTTIME (stream,
766               stream->samples[index].timestamp);
767           GST_DEBUG_OBJECT (qtdemux,
768               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
769               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
770           break;
771         }
772         default:
773           res = FALSE;
774           break;
775       }
776       break;
777     default:
778       res = FALSE;
779   }
780
781 done:
782   gst_object_unref (qtdemux);
783
784   return res;
785 }
786 #endif
787
788 static gboolean
789 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
790 {
791   gboolean res = TRUE;
792
793   *duration = GST_CLOCK_TIME_NONE;
794
795   if (qtdemux->duration != 0) {
796     if (qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
797       *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
798     }
799   }
800   return res;
801 }
802
803 static gboolean
804 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
805     GstQuery * query)
806 {
807   gboolean res = FALSE;
808   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
809
810   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
811
812   switch (GST_QUERY_TYPE (query)) {
813     case GST_QUERY_POSITION:{
814       GstFormat fmt;
815
816       gst_query_parse_position (query, &fmt, NULL);
817       if (fmt == GST_FORMAT_TIME
818           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
819         gst_query_set_position (query, GST_FORMAT_TIME,
820             qtdemux->segment.position);
821         res = TRUE;
822       }
823     }
824       break;
825     case GST_QUERY_DURATION:{
826       GstFormat fmt;
827
828       gst_query_parse_duration (query, &fmt, NULL);
829       if (fmt == GST_FORMAT_TIME) {
830         /* First try to query upstream */
831         res = gst_pad_query_default (pad, parent, query);
832         if (!res) {
833           guint64 duration;
834           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
835             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
836             res = TRUE;
837           }
838         }
839       }
840       break;
841     }
842     case GST_QUERY_CONVERT:{
843       GstFormat src_fmt, dest_fmt;
844       gint64 src_value, dest_value = 0;
845
846       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
847
848       res = gst_qtdemux_src_convert (pad,
849           src_fmt, src_value, dest_fmt, &dest_value);
850       if (res) {
851         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
852         res = TRUE;
853       }
854       break;
855     }
856     case GST_QUERY_FORMATS:
857       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
858       res = TRUE;
859       break;
860     case GST_QUERY_SEEKING:{
861       GstFormat fmt;
862       gboolean seekable;
863
864       /* try upstream first */
865       res = gst_pad_query_default (pad, parent, query);
866
867       if (!res) {
868         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
869         if (fmt == GST_FORMAT_TIME) {
870           GstClockTime duration = GST_CLOCK_TIME_NONE;
871
872           gst_qtdemux_get_duration (qtdemux, &duration);
873           seekable = TRUE;
874           if (!qtdemux->pullbased) {
875             GstQuery *q;
876
877             /* we might be able with help from upstream */
878             seekable = FALSE;
879             q = gst_query_new_seeking (GST_FORMAT_BYTES);
880             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
881               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
882               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
883             }
884             gst_query_unref (q);
885           }
886           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
887           res = TRUE;
888         }
889       }
890       break;
891     }
892     case GST_QUERY_SEGMENT:
893     {
894       GstFormat format;
895       gint64 start, stop;
896
897       format = qtdemux->segment.format;
898
899       start =
900           gst_segment_to_stream_time (&qtdemux->segment, format,
901           qtdemux->segment.start);
902       if ((stop = qtdemux->segment.stop) == -1)
903         stop = qtdemux->segment.duration;
904       else
905         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
906
907       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
908       res = TRUE;
909       break;
910     }
911     default:
912       res = gst_pad_query_default (pad, parent, query);
913       break;
914   }
915
916   return res;
917 }
918
919 static void
920 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
921 {
922   if (G_LIKELY (stream->pad)) {
923     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
924         GST_DEBUG_PAD_NAME (stream->pad));
925
926     if (G_UNLIKELY (stream->pending_tags)) {
927       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
928           stream->pending_tags);
929       gst_pad_push_event (stream->pad,
930           gst_event_new_tag (stream->pending_tags));
931       stream->pending_tags = NULL;
932     }
933
934     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
935       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
936           qtdemux->tag_list);
937       gst_pad_push_event (stream->pad,
938           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
939       stream->send_global_tags = FALSE;
940     }
941   }
942 }
943
944 /* push event on all source pads; takes ownership of the event */
945 static void
946 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
947 {
948   guint n;
949   gboolean has_valid_stream = FALSE;
950   GstEventType etype = GST_EVENT_TYPE (event);
951
952   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
953       GST_EVENT_TYPE_NAME (event));
954
955   for (n = 0; n < qtdemux->n_streams; n++) {
956     GstPad *pad;
957     QtDemuxStream *stream = qtdemux->streams[n];
958     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
959
960     if ((pad = stream->pad)) {
961       has_valid_stream = TRUE;
962
963       if (etype == GST_EVENT_EOS) {
964         /* let's not send twice */
965         if (stream->sent_eos)
966           continue;
967         stream->sent_eos = TRUE;
968       }
969
970       gst_pad_push_event (pad, gst_event_ref (event));
971     }
972   }
973
974   gst_event_unref (event);
975
976   /* if it is EOS and there are no pads, post an error */
977   if (!has_valid_stream && etype == GST_EVENT_EOS) {
978     gst_qtdemux_post_no_playable_stream_error (qtdemux);
979   }
980 }
981
982 /* push a pending newsegment event, if any from the streaming thread */
983 static void
984 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
985 {
986   if (qtdemux->pending_newsegment) {
987     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
988     qtdemux->pending_newsegment = NULL;
989   }
990 }
991
992 typedef struct
993 {
994   guint64 media_time;
995 } FindData;
996
997 static gint
998 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
999 {
1000   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1001     return 1;
1002   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1003     return 0;
1004
1005   return -1;
1006 }
1007
1008 /* find the index of the sample that includes the data for @media_time using a
1009  * binary search.  Only to be called in optimized cases of linear search below.
1010  *
1011  * Returns the index of the sample.
1012  */
1013 static guint32
1014 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1015     guint64 media_time)
1016 {
1017   QtDemuxSample *result;
1018   guint32 index;
1019
1020   /* convert media_time to mov format */
1021   media_time =
1022       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1023
1024   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1025       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1026       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1027
1028   if (G_LIKELY (result))
1029     index = result - str->samples;
1030   else
1031     index = 0;
1032
1033   return index;
1034 }
1035
1036
1037
1038 /* find the index of the sample that includes the data for @media_offset using a
1039  * linear search
1040  *
1041  * Returns the index of the sample.
1042  */
1043 static guint32
1044 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1045     QtDemuxStream * str, gint64 media_offset)
1046 {
1047   QtDemuxSample *result = str->samples;
1048   guint32 index = 0;
1049
1050   if (result == NULL || str->n_samples == 0)
1051     return -1;
1052
1053   if (media_offset == result->offset)
1054     return index;
1055
1056   result++;
1057   while (index < str->n_samples - 1) {
1058     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1059       goto parse_failed;
1060
1061     if (media_offset < result->offset)
1062       break;
1063
1064     index++;
1065     result++;
1066   }
1067   return index;
1068
1069   /* ERRORS */
1070 parse_failed:
1071   {
1072     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1073     return -1;
1074   }
1075 }
1076
1077 /* find the index of the sample that includes the data for @media_time using a
1078  * linear search, and keeping in mind that not all samples may have been parsed
1079  * yet.  If possible, it will delegate to binary search.
1080  *
1081  * Returns the index of the sample.
1082  */
1083 static guint32
1084 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1085     GstClockTime media_time)
1086 {
1087   guint32 index = 0;
1088   guint64 mov_time;
1089   QtDemuxSample *sample;
1090
1091   /* convert media_time to mov format */
1092   mov_time =
1093       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1094
1095   sample = str->samples;
1096   if (mov_time == sample->timestamp + sample->pts_offset)
1097     return index;
1098
1099   /* use faster search if requested time in already parsed range */
1100   sample = str->samples + str->stbl_index;
1101   if (str->stbl_index >= 0 &&
1102       mov_time <= (sample->timestamp + sample->pts_offset))
1103     return gst_qtdemux_find_index (qtdemux, str, media_time);
1104
1105   while (index < str->n_samples - 1) {
1106     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1107       goto parse_failed;
1108
1109     sample = str->samples + index + 1;
1110     if (mov_time < (sample->timestamp + sample->pts_offset))
1111       break;
1112
1113     index++;
1114   }
1115   return index;
1116
1117   /* ERRORS */
1118 parse_failed:
1119   {
1120     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1121     return -1;
1122   }
1123 }
1124
1125 /* find the index of the keyframe needed to decode the sample at @index
1126  * of stream @str.
1127  *
1128  * Returns the index of the keyframe.
1129  */
1130 static guint32
1131 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1132     guint32 index)
1133 {
1134   guint32 new_index = index;
1135
1136   if (index >= str->n_samples) {
1137     new_index = str->n_samples;
1138     goto beach;
1139   }
1140
1141   /* all keyframes, return index */
1142   if (str->all_keyframe) {
1143     new_index = index;
1144     goto beach;
1145   }
1146
1147   /* else go back until we have a keyframe */
1148   while (TRUE) {
1149     if (str->samples[new_index].keyframe)
1150       break;
1151
1152     if (new_index == 0)
1153       break;
1154
1155     new_index--;
1156   }
1157
1158 beach:
1159   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1160       "gave %u", index, new_index);
1161
1162   return new_index;
1163 }
1164
1165 /* find the segment for @time_position for @stream
1166  *
1167  * Returns the index of the segment containing @time_position.
1168  * Returns the last segment and sets the @eos variable to TRUE
1169  * if the time is beyond the end. @eos may be NULL
1170  */
1171 static guint32
1172 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1173     GstClockTime time_position)
1174 {
1175   gint i;
1176   guint32 seg_idx;
1177
1178   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1179       GST_TIME_ARGS (time_position));
1180
1181   seg_idx = -1;
1182   for (i = 0; i < stream->n_segments; i++) {
1183     QtDemuxSegment *segment = &stream->segments[i];
1184
1185     GST_LOG_OBJECT (stream->pad,
1186         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1187         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1188
1189     /* For the last segment we include stop_time in the last segment */
1190     if (i < stream->n_segments - 1) {
1191       if (segment->time <= time_position && time_position < segment->stop_time) {
1192         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1193         seg_idx = i;
1194         break;
1195       }
1196     } else {
1197       /* Last segment always matches */
1198       seg_idx = i;
1199       break;
1200     }
1201   }
1202   return seg_idx;
1203 }
1204
1205 /* move the stream @str to the sample position @index.
1206  *
1207  * Updates @str->sample_index and marks discontinuity if needed.
1208  */
1209 static void
1210 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1211     guint32 index)
1212 {
1213   /* no change needed */
1214   if (index == str->sample_index)
1215     return;
1216
1217   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1218       str->n_samples);
1219
1220   /* position changed, we have a discont */
1221   str->sample_index = index;
1222   str->offset_in_sample = 0;
1223   /* Each time we move in the stream we store the position where we are
1224    * starting from */
1225   str->from_sample = index;
1226   str->discont = TRUE;
1227 }
1228
1229 static void
1230 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1231     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1232 {
1233   guint64 min_offset;
1234   gint64 min_byte_offset = -1;
1235   gint n;
1236
1237   min_offset = desired_time;
1238
1239   /* for each stream, find the index of the sample in the segment
1240    * and move back to the previous keyframe. */
1241   for (n = 0; n < qtdemux->n_streams; n++) {
1242     QtDemuxStream *str;
1243     guint32 index, kindex;
1244     guint32 seg_idx;
1245     GstClockTime media_start;
1246     GstClockTime media_time;
1247     GstClockTime seg_time;
1248     QtDemuxSegment *seg;
1249     gboolean empty_segment = FALSE;
1250
1251     str = qtdemux->streams[n];
1252
1253     if (str->sparse && !use_sparse)
1254       continue;
1255
1256     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1257     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1258
1259     /* get segment and time in the segment */
1260     seg = &str->segments[seg_idx];
1261     seg_time = desired_time - seg->time;
1262
1263     while (QTSEGMENT_IS_EMPTY (seg)) {
1264       seg_time = 0;
1265       empty_segment = TRUE;
1266       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1267           seg_idx);
1268       seg_idx++;
1269       if (seg_idx == str->n_segments)
1270         break;
1271       seg = &str->segments[seg_idx];
1272     }
1273
1274     if (seg_idx == str->n_segments) {
1275       /* FIXME track shouldn't have the last segment as empty, but if it
1276        * happens we better handle it */
1277       continue;
1278     }
1279
1280     /* get the media time in the segment */
1281     media_start = seg->media_start + seg_time;
1282
1283     /* get the index of the sample with media time */
1284     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1285     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1286         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1287         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1288         empty_segment);
1289
1290     if (!empty_segment) {
1291       /* find previous keyframe */
1292       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1293
1294       /* if the keyframe is at a different position, we need to update the
1295        * requested seek time */
1296       if (index != kindex) {
1297         index = kindex;
1298
1299         /* get timestamp of keyframe */
1300         media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1301         GST_DEBUG_OBJECT (qtdemux,
1302             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1303             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1304             str->samples[kindex].offset);
1305
1306         /* keyframes in the segment get a chance to change the
1307          * desired_offset. keyframes out of the segment are
1308          * ignored. */
1309         if (media_time >= seg->media_start) {
1310           GstClockTime seg_time;
1311
1312           /* this keyframe is inside the segment, convert back to
1313            * segment time */
1314           seg_time = (media_time - seg->media_start) + seg->time;
1315           if (seg_time < min_offset)
1316             min_offset = seg_time;
1317         }
1318       }
1319     }
1320
1321     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1322       min_byte_offset = str->samples[index].offset;
1323   }
1324
1325   if (key_time)
1326     *key_time = min_offset;
1327   if (key_offset)
1328     *key_offset = min_byte_offset;
1329 }
1330
1331 static gboolean
1332 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1333     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1334 {
1335   gboolean res;
1336
1337   g_return_val_if_fail (format != NULL, FALSE);
1338   g_return_val_if_fail (cur != NULL, FALSE);
1339   g_return_val_if_fail (stop != NULL, FALSE);
1340
1341   if (*format == GST_FORMAT_TIME)
1342     return TRUE;
1343
1344   res = TRUE;
1345   if (cur_type != GST_SEEK_TYPE_NONE)
1346     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1347   if (res && stop_type != GST_SEEK_TYPE_NONE)
1348     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1349
1350   if (res)
1351     *format = GST_FORMAT_TIME;
1352
1353   return res;
1354 }
1355
1356 /* perform seek in push based mode:
1357    find BYTE position to move to based on time and delegate to upstream
1358 */
1359 static gboolean
1360 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1361 {
1362   gdouble rate;
1363   GstFormat format;
1364   GstSeekFlags flags;
1365   GstSeekType cur_type, stop_type;
1366   gint64 cur, stop, key_cur;
1367   gboolean res;
1368   gint64 byte_cur;
1369   gint64 original_stop;
1370   guint32 seqnum;
1371
1372   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1373
1374   gst_event_parse_seek (event, &rate, &format, &flags,
1375       &cur_type, &cur, &stop_type, &stop);
1376   seqnum = gst_event_get_seqnum (event);
1377
1378   /* only forward streaming and seeking is possible */
1379   if (rate <= 0)
1380     goto unsupported_seek;
1381
1382   /* convert to TIME if needed and possible */
1383   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1384           stop_type, &stop))
1385     goto no_format;
1386
1387   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1388    * the original stop position to use when upstream pushes the new segment
1389    * for this seek */
1390   original_stop = stop;
1391   stop = -1;
1392
1393   /* find reasonable corresponding BYTE position,
1394    * also try to mind about keyframes, since we can not go back a bit for them
1395    * later on */
1396   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1397
1398   if (byte_cur == -1)
1399     goto abort_seek;
1400
1401   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1402       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1403       stop);
1404
1405   GST_OBJECT_LOCK (qtdemux);
1406   qtdemux->seek_offset = byte_cur;
1407   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1408     qtdemux->push_seek_start = cur;
1409   } else {
1410     qtdemux->push_seek_start = key_cur;
1411   }
1412
1413   if (stop_type == GST_SEEK_TYPE_NONE) {
1414     qtdemux->push_seek_stop = qtdemux->segment.stop;
1415   } else {
1416     qtdemux->push_seek_stop = original_stop;
1417   }
1418   GST_OBJECT_UNLOCK (qtdemux);
1419
1420   /* BYTE seek event */
1421   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1422       stop_type, stop);
1423   gst_event_set_seqnum (event, seqnum);
1424   res = gst_pad_push_event (qtdemux->sinkpad, event);
1425
1426   return res;
1427
1428   /* ERRORS */
1429 abort_seek:
1430   {
1431     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1432         "seek aborted.");
1433     return FALSE;
1434   }
1435 unsupported_seek:
1436   {
1437     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1438     return FALSE;
1439   }
1440 no_format:
1441   {
1442     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1443     return FALSE;
1444   }
1445 }
1446
1447 /* perform the seek.
1448  *
1449  * We set all segment_indexes in the streams to unknown and
1450  * adjust the time_position to the desired position. this is enough
1451  * to trigger a segment switch in the streaming thread to start
1452  * streaming from the desired position.
1453  *
1454  * Keyframe seeking is a little more complicated when dealing with
1455  * segments. Ideally we want to move to the previous keyframe in
1456  * the segment but there might not be a keyframe in the segment. In
1457  * fact, none of the segments could contain a keyframe. We take a
1458  * practical approach: seek to the previous keyframe in the segment,
1459  * if there is none, seek to the beginning of the segment.
1460  *
1461  * Called with STREAM_LOCK
1462  */
1463 static gboolean
1464 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1465     guint32 seqnum, GstSeekFlags flags)
1466 {
1467   gint64 desired_offset;
1468   gint n;
1469
1470   desired_offset = segment->position;
1471
1472   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1473       GST_TIME_ARGS (desired_offset));
1474
1475   /* may not have enough fragmented info to do this adjustment,
1476    * and we can't scan (and probably should not) at this time with
1477    * possibly flushing upstream */
1478   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1479     gint64 min_offset;
1480
1481     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1482     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1483         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1484     desired_offset = min_offset;
1485   }
1486
1487   /* and set all streams to the final position */
1488   gst_flow_combiner_reset (qtdemux->flowcombiner);
1489   for (n = 0; n < qtdemux->n_streams; n++) {
1490     QtDemuxStream *stream = qtdemux->streams[n];
1491
1492     stream->time_position = desired_offset;
1493     stream->accumulated_base = 0;
1494     stream->sample_index = -1;
1495     stream->offset_in_sample = 0;
1496     stream->segment_index = -1;
1497     stream->sent_eos = FALSE;
1498     stream->segment_seqnum = seqnum;
1499
1500     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1501       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1502   }
1503   segment->position = desired_offset;
1504   segment->time = desired_offset;
1505   if (segment->rate >= 0) {
1506     segment->start = desired_offset;
1507
1508     /* we stop at the end */
1509     if (segment->stop == -1)
1510       segment->stop = segment->duration;
1511   } else {
1512     segment->stop = desired_offset;
1513   }
1514
1515   if (qtdemux->fragmented)
1516     qtdemux->fragmented_seek_pending = TRUE;
1517
1518   return TRUE;
1519 }
1520
1521 /* do a seek in pull based mode */
1522 static gboolean
1523 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1524 {
1525   gdouble rate;
1526   GstFormat format;
1527   GstSeekFlags flags;
1528   GstSeekType cur_type, stop_type;
1529   gint64 cur, stop;
1530   gboolean flush;
1531   gboolean update;
1532   GstSegment seeksegment;
1533   guint32 seqnum = 0;
1534   GstEvent *flush_event;
1535
1536   if (event) {
1537     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1538
1539     gst_event_parse_seek (event, &rate, &format, &flags,
1540         &cur_type, &cur, &stop_type, &stop);
1541     seqnum = gst_event_get_seqnum (event);
1542
1543     /* we have to have a format as the segment format. Try to convert
1544      * if not. */
1545     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1546             stop_type, &stop))
1547       goto no_format;
1548
1549     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1550   } else {
1551     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1552     flags = 0;
1553   }
1554
1555   flush = flags & GST_SEEK_FLAG_FLUSH;
1556
1557   /* stop streaming, either by flushing or by pausing the task */
1558   if (flush) {
1559     flush_event = gst_event_new_flush_start ();
1560     if (seqnum)
1561       gst_event_set_seqnum (flush_event, seqnum);
1562     /* unlock upstream pull_range */
1563     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1564     /* make sure out loop function exits */
1565     gst_qtdemux_push_event (qtdemux, flush_event);
1566   } else {
1567     /* non flushing seek, pause the task */
1568     gst_pad_pause_task (qtdemux->sinkpad);
1569   }
1570
1571   /* wait for streaming to finish */
1572   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1573
1574   /* copy segment, we need this because we still need the old
1575    * segment when we close the current segment. */
1576   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1577
1578   if (event) {
1579     /* configure the segment with the seek variables */
1580     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1581     gst_segment_do_seek (&seeksegment, rate, format, flags,
1582         cur_type, cur, stop_type, stop, &update);
1583   }
1584
1585   /* now do the seek, this actually never returns FALSE */
1586   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1587
1588   /* prepare for streaming again */
1589   if (flush) {
1590     flush_event = gst_event_new_flush_stop (TRUE);
1591     if (seqnum)
1592       gst_event_set_seqnum (flush_event, seqnum);
1593
1594     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1595     gst_qtdemux_push_event (qtdemux, flush_event);
1596   }
1597
1598   /* commit the new segment */
1599   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1600
1601   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1602     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1603         qtdemux->segment.format, qtdemux->segment.position);
1604     if (seqnum)
1605       gst_message_set_seqnum (msg, seqnum);
1606     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1607   }
1608
1609   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1610   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1611       qtdemux->sinkpad, NULL);
1612
1613   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1614
1615   return TRUE;
1616
1617   /* ERRORS */
1618 no_format:
1619   {
1620     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1621     return FALSE;
1622   }
1623 }
1624
1625 static gboolean
1626 qtdemux_ensure_index (GstQTDemux * qtdemux)
1627 {
1628   guint i;
1629
1630   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1631
1632   /* Build complete index */
1633   for (i = 0; i < qtdemux->n_streams; i++) {
1634     QtDemuxStream *stream = qtdemux->streams[i];
1635
1636     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1637       goto parse_error;
1638   }
1639   return TRUE;
1640
1641   /* ERRORS */
1642 parse_error:
1643   {
1644     GST_LOG_OBJECT (qtdemux,
1645         "Building complete index of stream %u for seeking failed!", i);
1646     return FALSE;
1647   }
1648 }
1649
1650 static gboolean
1651 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1652     GstEvent * event)
1653 {
1654   gboolean res = TRUE;
1655   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1656
1657   switch (GST_EVENT_TYPE (event)) {
1658     case GST_EVENT_SEEK:
1659     {
1660 #ifndef GST_DISABLE_GST_DEBUG
1661       GstClockTime ts = gst_util_get_timestamp ();
1662 #endif
1663
1664       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1665         /* seek should be handled by upstream, we might need to re-download fragments */
1666         GST_DEBUG_OBJECT (qtdemux,
1667             "let upstream handle seek for fragmented playback");
1668         goto upstream;
1669       }
1670
1671       /* Build complete index for seeking;
1672        * if not a fragmented file at least */
1673       if (!qtdemux->fragmented)
1674         if (!qtdemux_ensure_index (qtdemux))
1675           goto index_failed;
1676 #ifndef GST_DISABLE_GST_DEBUG
1677       ts = gst_util_get_timestamp () - ts;
1678       GST_INFO_OBJECT (qtdemux,
1679           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1680 #endif
1681     }
1682       if (qtdemux->pullbased) {
1683         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1684       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1685         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1686         res = TRUE;
1687       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1688           && !qtdemux->fragmented) {
1689         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1690       } else {
1691         GST_DEBUG_OBJECT (qtdemux,
1692             "ignoring seek in push mode in current state");
1693         res = FALSE;
1694       }
1695       gst_event_unref (event);
1696       break;
1697     case GST_EVENT_QOS:
1698     case GST_EVENT_NAVIGATION:
1699       res = FALSE;
1700       gst_event_unref (event);
1701       break;
1702     default:
1703     upstream:
1704       res = gst_pad_event_default (pad, parent, event);
1705       break;
1706   }
1707
1708 done:
1709   return res;
1710
1711   /* ERRORS */
1712 index_failed:
1713   {
1714     GST_ERROR_OBJECT (qtdemux, "Index failed");
1715     gst_event_unref (event);
1716     res = FALSE;
1717     goto done;
1718   }
1719 }
1720
1721 /* stream/index return sample that is min/max w.r.t. byte position,
1722  * time is min/max w.r.t. time of samples,
1723  * the latter need not be time of the former sample */
1724 static void
1725 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1726     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1727 {
1728   gint i, n, index;
1729   gint64 time, min_time;
1730   QtDemuxStream *stream;
1731
1732   min_time = -1;
1733   stream = NULL;
1734   index = -1;
1735
1736   for (n = 0; n < qtdemux->n_streams; ++n) {
1737     QtDemuxStream *str;
1738     gint inc;
1739     gboolean set_sample;
1740
1741     str = qtdemux->streams[n];
1742     set_sample = !set;
1743
1744     if (fw) {
1745       i = 0;
1746       inc = 1;
1747     } else {
1748       i = str->n_samples - 1;
1749       inc = -1;
1750     }
1751
1752     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1753       if (str->samples[i].size == 0)
1754         continue;
1755
1756       if (fw && (str->samples[i].offset < byte_pos))
1757         continue;
1758
1759       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1760         continue;
1761
1762       /* move stream to first available sample */
1763       if (set) {
1764         gst_qtdemux_move_stream (qtdemux, str, i);
1765         set_sample = TRUE;
1766       }
1767
1768       /* avoid index from sparse streams since they might be far away */
1769       if (!str->sparse) {
1770         /* determine min/max time */
1771         time = QTSAMPLE_PTS (str, &str->samples[i]);
1772         if (min_time == -1 || (!fw && time > min_time) ||
1773             (fw && time < min_time)) {
1774           min_time = time;
1775         }
1776
1777         /* determine stream with leading sample, to get its position */
1778         if (!stream ||
1779             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1780             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1781           stream = str;
1782           index = i;
1783         }
1784       }
1785       break;
1786     }
1787
1788     /* no sample for this stream, mark eos */
1789     if (!set_sample)
1790       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1791   }
1792
1793   if (_time)
1794     *_time = min_time;
1795   if (_stream)
1796     *_stream = stream;
1797   if (_index)
1798     *_index = index;
1799 }
1800
1801 static QtDemuxStream *
1802 _create_stream (void)
1803 {
1804   QtDemuxStream *stream;
1805
1806   stream = g_new0 (QtDemuxStream, 1);
1807   /* new streams always need a discont */
1808   stream->discont = TRUE;
1809   /* we enable clipping for raw audio/video streams */
1810   stream->need_clip = FALSE;
1811   stream->need_process = FALSE;
1812   stream->segment_index = -1;
1813   stream->time_position = 0;
1814   stream->sample_index = -1;
1815   stream->offset_in_sample = 0;
1816   stream->new_stream = TRUE;
1817   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1818   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1819   stream->protected = FALSE;
1820   stream->protection_scheme_type = 0;
1821   stream->protection_scheme_version = 0;
1822   stream->protection_scheme_info = NULL;
1823   stream->n_samples_moof = 0;
1824   stream->duration_moof = 0;
1825   g_queue_init (&stream->protection_scheme_event_queue);
1826   return stream;
1827 }
1828
1829 static gboolean
1830 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1831 {
1832   GstStructure *structure;
1833   const gchar *variant;
1834   const GstCaps *mediacaps = NULL;
1835
1836   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1837
1838   structure = gst_caps_get_structure (caps, 0);
1839   variant = gst_structure_get_string (structure, "variant");
1840
1841   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1842     QtDemuxStream *stream;
1843     const GValue *value;
1844
1845     demux->fragmented = TRUE;
1846     demux->mss_mode = TRUE;
1847
1848     if (demux->n_streams > 1) {
1849       /* can't do this, we can only renegotiate for another mss format */
1850       return FALSE;
1851     }
1852
1853     value = gst_structure_get_value (structure, "media-caps");
1854     /* create stream */
1855     if (value) {
1856       const GValue *timescale_v;
1857
1858       /* TODO update when stream changes during playback */
1859
1860       if (demux->n_streams == 0) {
1861         stream = _create_stream ();
1862         demux->streams[demux->n_streams] = stream;
1863         demux->n_streams = 1;
1864       } else {
1865         stream = demux->streams[0];
1866       }
1867
1868       timescale_v = gst_structure_get_value (structure, "timescale");
1869       if (timescale_v) {
1870         stream->timescale = g_value_get_uint64 (timescale_v);
1871       } else {
1872         /* default mss timescale */
1873         stream->timescale = 10000000;
1874       }
1875       demux->timescale = stream->timescale;
1876
1877       mediacaps = gst_value_get_caps (value);
1878       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1879         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1880             mediacaps);
1881         stream->new_caps = TRUE;
1882       }
1883       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1884       structure = gst_caps_get_structure (mediacaps, 0);
1885       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1886         stream->subtype = FOURCC_vide;
1887
1888         gst_structure_get_int (structure, "width", &stream->width);
1889         gst_structure_get_int (structure, "height", &stream->height);
1890         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1891             &stream->fps_d);
1892       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1893         gint rate = 0;
1894         stream->subtype = FOURCC_soun;
1895         gst_structure_get_int (structure, "channels", &stream->n_channels);
1896         gst_structure_get_int (structure, "rate", &rate);
1897         stream->rate = rate;
1898       }
1899     }
1900     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1901   } else {
1902     demux->mss_mode = FALSE;
1903   }
1904
1905   return TRUE;
1906 }
1907
1908 static void
1909 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1910 {
1911   gint n;
1912
1913   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1914   gst_pad_stop_task (qtdemux->sinkpad);
1915
1916   if (hard || qtdemux->upstream_format_is_time) {
1917     qtdemux->state = QTDEMUX_STATE_INITIAL;
1918     qtdemux->neededbytes = 16;
1919     qtdemux->todrop = 0;
1920     qtdemux->pullbased = FALSE;
1921     qtdemux->posted_redirect = FALSE;
1922     qtdemux->first_mdat = -1;
1923     qtdemux->header_size = 0;
1924     qtdemux->mdatoffset = -1;
1925     qtdemux->restoredata_offset = -1;
1926     if (qtdemux->mdatbuffer)
1927       gst_buffer_unref (qtdemux->mdatbuffer);
1928     if (qtdemux->restoredata_buffer)
1929       gst_buffer_unref (qtdemux->restoredata_buffer);
1930     qtdemux->mdatbuffer = NULL;
1931     qtdemux->restoredata_buffer = NULL;
1932     qtdemux->mdatleft = 0;
1933     if (qtdemux->comp_brands)
1934       gst_buffer_unref (qtdemux->comp_brands);
1935     qtdemux->comp_brands = NULL;
1936     qtdemux->last_moov_offset = -1;
1937     if (qtdemux->moov_node)
1938       g_node_destroy (qtdemux->moov_node);
1939     qtdemux->moov_node = NULL;
1940     qtdemux->moov_node_compressed = NULL;
1941     if (qtdemux->tag_list)
1942       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1943     qtdemux->tag_list = NULL;
1944 #if 0
1945     if (qtdemux->element_index)
1946       gst_object_unref (qtdemux->element_index);
1947     qtdemux->element_index = NULL;
1948 #endif
1949     qtdemux->major_brand = 0;
1950     if (qtdemux->pending_newsegment)
1951       gst_event_unref (qtdemux->pending_newsegment);
1952     qtdemux->pending_newsegment = NULL;
1953     qtdemux->upstream_format_is_time = FALSE;
1954     qtdemux->upstream_seekable = FALSE;
1955     qtdemux->upstream_size = 0;
1956
1957     qtdemux->fragment_start = -1;
1958     qtdemux->fragment_start_offset = -1;
1959     qtdemux->duration = 0;
1960     qtdemux->moof_offset = 0;
1961     qtdemux->chapters_track_id = 0;
1962     qtdemux->have_group_id = FALSE;
1963     qtdemux->group_id = G_MAXUINT;
1964
1965     if (qtdemux->protection_system_ids) {
1966       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
1967       qtdemux->protection_system_ids = NULL;
1968     }
1969     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1970         NULL);
1971     g_queue_clear (&qtdemux->protection_event_queue);
1972   }
1973   qtdemux->offset = 0;
1974   gst_adapter_clear (qtdemux->adapter);
1975   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1976
1977   if (hard) {
1978     for (n = 0; n < qtdemux->n_streams; n++) {
1979       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
1980       qtdemux->streams[n] = NULL;
1981     }
1982     qtdemux->n_streams = 0;
1983     qtdemux->n_video_streams = 0;
1984     qtdemux->n_audio_streams = 0;
1985     qtdemux->n_sub_streams = 0;
1986     qtdemux->exposed = FALSE;
1987     qtdemux->fragmented = FALSE;
1988     qtdemux->mss_mode = FALSE;
1989     gst_caps_replace (&qtdemux->media_caps, NULL);
1990     qtdemux->timescale = 0;
1991     qtdemux->got_moov = FALSE;
1992     qtdemux->pending_configure = FALSE;
1993   } else if (qtdemux->mss_mode) {
1994     gst_flow_combiner_reset (qtdemux->flowcombiner);
1995     for (n = 0; n < qtdemux->n_streams; n++)
1996       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
1997   } else {
1998     gst_flow_combiner_reset (qtdemux->flowcombiner);
1999     for (n = 0; n < qtdemux->n_streams; n++) {
2000       qtdemux->streams[n]->sent_eos = FALSE;
2001       qtdemux->streams[n]->segment_seqnum = 0;
2002       qtdemux->streams[n]->time_position = 0;
2003       qtdemux->streams[n]->accumulated_base = 0;
2004     }
2005     if (!qtdemux->pending_newsegment) {
2006       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2007     }
2008   }
2009 }
2010
2011 static gboolean
2012 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2013     GstEvent * event)
2014 {
2015   GstQTDemux *demux = GST_QTDEMUX (parent);
2016   gboolean res = TRUE;
2017
2018   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2019
2020   switch (GST_EVENT_TYPE (event)) {
2021     case GST_EVENT_SEGMENT:
2022     {
2023       gint64 offset = 0;
2024       QtDemuxStream *stream;
2025       gint idx;
2026       GstSegment segment;
2027       GstEvent *segment_event;
2028
2029       /* some debug output */
2030       gst_event_copy_segment (event, &segment);
2031       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2032           &segment);
2033
2034       if (segment.format == GST_FORMAT_TIME) {
2035         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2036         gst_event_replace (&demux->pending_newsegment, event);
2037         demux->upstream_format_is_time = TRUE;
2038       } else {
2039         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2040             "not in time format");
2041
2042         /* chain will send initial newsegment after pads have been added */
2043         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2044           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2045           goto exit;
2046         }
2047       }
2048
2049       /* check if this matches a time seek we received previously
2050        * FIXME for backwards compatibility reasons we use the
2051        * seek_offset here to compare. In the future we might want to
2052        * change this to use the seqnum as it uniquely should identify
2053        * the segment that corresponds to the seek. */
2054       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2055           ", received segment offset %" G_GINT64_FORMAT,
2056           demux->seek_offset, segment.start);
2057       if (segment.format == GST_FORMAT_BYTES
2058           && demux->seek_offset == segment.start) {
2059         GST_OBJECT_LOCK (demux);
2060         offset = segment.start;
2061
2062         segment.format = GST_FORMAT_TIME;
2063         segment.start = demux->push_seek_start;
2064         segment.stop = demux->push_seek_stop;
2065         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2066             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2067             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2068         GST_OBJECT_UNLOCK (demux);
2069       }
2070
2071       /* we only expect a BYTE segment, e.g. following a seek */
2072       if (segment.format == GST_FORMAT_BYTES) {
2073         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2074           offset = segment.start;
2075
2076           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2077               NULL, (gint64 *) & segment.start);
2078           if ((gint64) segment.start < 0)
2079             segment.start = 0;
2080         }
2081         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2082           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2083               NULL, (gint64 *) & segment.stop);
2084           /* keyframe seeking should already arrange for start >= stop,
2085            * but make sure in other rare cases */
2086           segment.stop = MAX (segment.stop, segment.start);
2087         }
2088       } else if (segment.format == GST_FORMAT_TIME) {
2089         /* push all data on the adapter before starting this
2090          * new segment */
2091         gst_qtdemux_process_adapter (demux, TRUE);
2092       } else {
2093         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2094         goto exit;
2095       }
2096
2097       /* accept upstream's notion of segment and distribute along */
2098       segment.format = GST_FORMAT_TIME;
2099       segment.position = segment.time = segment.start;
2100       segment.duration = demux->segment.duration;
2101       segment.base = gst_segment_to_running_time (&demux->segment,
2102           GST_FORMAT_TIME, demux->segment.position);
2103
2104       gst_segment_copy_into (&segment, &demux->segment);
2105       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2106       segment_event = gst_event_new_segment (&segment);
2107       gst_event_set_seqnum (segment_event, gst_event_get_seqnum (event));
2108       gst_qtdemux_push_event (demux, segment_event);
2109
2110       /* clear leftover in current segment, if any */
2111       gst_adapter_clear (demux->adapter);
2112
2113       /* set up streaming thread */
2114       demux->offset = offset;
2115       if (demux->upstream_format_is_time) {
2116         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2117             "set values to restart reading from a new atom");
2118         demux->neededbytes = 16;
2119         demux->todrop = 0;
2120       } else {
2121         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2122             NULL);
2123         if (stream) {
2124           demux->todrop = stream->samples[idx].offset - offset;
2125           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2126         } else {
2127           /* set up for EOS */
2128           demux->neededbytes = -1;
2129           demux->todrop = 0;
2130         }
2131       }
2132     exit:
2133       gst_event_unref (event);
2134       res = TRUE;
2135       goto drop;
2136     }
2137     case GST_EVENT_FLUSH_START:
2138     {
2139       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2140         gst_event_unref (event);
2141         goto drop;
2142       }
2143       break;
2144     }
2145     case GST_EVENT_FLUSH_STOP:
2146     {
2147       guint64 dur;
2148
2149       dur = demux->segment.duration;
2150       gst_qtdemux_reset (demux, FALSE);
2151       demux->segment.duration = dur;
2152
2153       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2154         gst_event_unref (event);
2155         goto drop;
2156       }
2157       break;
2158     }
2159     case GST_EVENT_EOS:
2160       /* If we are in push mode, and get an EOS before we've seen any streams,
2161        * then error out - we have nowhere to send the EOS */
2162       if (!demux->pullbased) {
2163         gint i;
2164         gboolean has_valid_stream = FALSE;
2165         for (i = 0; i < demux->n_streams; i++) {
2166           if (demux->streams[i]->pad != NULL) {
2167             has_valid_stream = TRUE;
2168             break;
2169           }
2170         }
2171         if (!has_valid_stream)
2172           gst_qtdemux_post_no_playable_stream_error (demux);
2173         else {
2174           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2175               (guint) gst_adapter_available (demux->adapter));
2176           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2177             res = FALSE;
2178           }
2179         }
2180       }
2181       break;
2182     case GST_EVENT_CAPS:{
2183       GstCaps *caps = NULL;
2184
2185       gst_event_parse_caps (event, &caps);
2186       gst_qtdemux_setcaps (demux, caps);
2187       res = TRUE;
2188       gst_event_unref (event);
2189       goto drop;
2190     }
2191     case GST_EVENT_PROTECTION:
2192     {
2193       const gchar *system_id = NULL;
2194
2195       gst_event_parse_protection (event, &system_id, NULL, NULL);
2196       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2197           system_id);
2198       gst_qtdemux_append_protection_system_id (demux, system_id);
2199       /* save the event for later, for source pads that have not been created */
2200       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2201       /* send it to all pads that already exist */
2202       gst_qtdemux_push_event (demux, event);
2203       res = TRUE;
2204       goto drop;
2205     }
2206     default:
2207       break;
2208   }
2209
2210   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2211
2212 drop:
2213   return res;
2214 }
2215
2216 #if 0
2217 static void
2218 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2219 {
2220   GstQTDemux *demux = GST_QTDEMUX (element);
2221
2222   GST_OBJECT_LOCK (demux);
2223   if (demux->element_index)
2224     gst_object_unref (demux->element_index);
2225   if (index) {
2226     demux->element_index = gst_object_ref (index);
2227   } else {
2228     demux->element_index = NULL;
2229   }
2230   GST_OBJECT_UNLOCK (demux);
2231   /* object lock might be taken again */
2232   if (index)
2233     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2234   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2235       demux->element_index, demux->index_id);
2236 }
2237
2238 static GstIndex *
2239 gst_qtdemux_get_index (GstElement * element)
2240 {
2241   GstIndex *result = NULL;
2242   GstQTDemux *demux = GST_QTDEMUX (element);
2243
2244   GST_OBJECT_LOCK (demux);
2245   if (demux->element_index)
2246     result = gst_object_ref (demux->element_index);
2247   GST_OBJECT_UNLOCK (demux);
2248
2249   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2250
2251   return result;
2252 }
2253 #endif
2254
2255 static void
2256 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2257 {
2258   g_free ((gpointer) stream->stco.data);
2259   stream->stco.data = NULL;
2260   g_free ((gpointer) stream->stsz.data);
2261   stream->stsz.data = NULL;
2262   g_free ((gpointer) stream->stsc.data);
2263   stream->stsc.data = NULL;
2264   g_free ((gpointer) stream->stts.data);
2265   stream->stts.data = NULL;
2266   g_free ((gpointer) stream->stss.data);
2267   stream->stss.data = NULL;
2268   g_free ((gpointer) stream->stps.data);
2269   stream->stps.data = NULL;
2270   g_free ((gpointer) stream->ctts.data);
2271   stream->ctts.data = NULL;
2272 }
2273
2274 static void
2275 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2276     QtDemuxStream * stream)
2277 {
2278   g_free (stream->segments);
2279   stream->segments = NULL;
2280   stream->segment_index = -1;
2281   stream->accumulated_base = 0;
2282 }
2283
2284 static void
2285 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2286     QtDemuxStream * stream)
2287 {
2288   g_free (stream->samples);
2289   stream->samples = NULL;
2290   gst_qtdemux_stbl_free (stream);
2291
2292   /* fragments */
2293   g_free (stream->ra_entries);
2294   stream->ra_entries = NULL;
2295   stream->n_ra_entries = 0;
2296
2297   stream->sample_index = -1;
2298   stream->stbl_index = -1;
2299   stream->n_samples = 0;
2300   stream->time_position = 0;
2301
2302   stream->n_samples_moof = 0;
2303   stream->duration_moof = 0;
2304 }
2305
2306 static void
2307 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2308 {
2309   if (stream->allocator)
2310     gst_object_unref (stream->allocator);
2311   while (stream->buffers) {
2312     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2313     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2314   }
2315   if (stream->rgb8_palette) {
2316     gst_memory_unref (stream->rgb8_palette);
2317     stream->rgb8_palette = NULL;
2318   }
2319
2320   if (stream->pending_tags)
2321     gst_tag_list_unref (stream->pending_tags);
2322   stream->pending_tags = NULL;
2323   g_free (stream->redirect_uri);
2324   stream->redirect_uri = NULL;
2325   stream->sent_eos = FALSE;
2326   stream->sparse = FALSE;
2327   stream->protected = FALSE;
2328   if (stream->protection_scheme_info) {
2329     if (stream->protection_scheme_type == FOURCC_cenc) {
2330       QtDemuxCencSampleSetInfo *info =
2331           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2332       if (info->default_properties)
2333         gst_structure_free (info->default_properties);
2334       if (info->crypto_info)
2335         g_ptr_array_free (info->crypto_info, TRUE);
2336     }
2337     g_free (stream->protection_scheme_info);
2338     stream->protection_scheme_info = NULL;
2339   }
2340   stream->protection_scheme_type = 0;
2341   stream->protection_scheme_version = 0;
2342   g_queue_foreach (&stream->protection_scheme_event_queue,
2343       (GFunc) gst_event_unref, NULL);
2344   g_queue_clear (&stream->protection_scheme_event_queue);
2345   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2346   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2347 }
2348
2349 static void
2350 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2351 {
2352   gst_qtdemux_stream_clear (qtdemux, stream);
2353   if (stream->caps)
2354     gst_caps_unref (stream->caps);
2355   stream->caps = NULL;
2356   if (stream->pad) {
2357     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2358     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2359   }
2360   g_free (stream);
2361 }
2362
2363 static void
2364 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2365 {
2366   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2367
2368   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2369   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2370   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2371   qtdemux->n_streams--;
2372 }
2373
2374 static GstStateChangeReturn
2375 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2376 {
2377   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2378   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2379
2380   switch (transition) {
2381     case GST_STATE_CHANGE_PAUSED_TO_READY:
2382       break;
2383     default:
2384       break;
2385   }
2386
2387   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2388
2389   switch (transition) {
2390     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2391       gst_qtdemux_reset (qtdemux, TRUE);
2392       break;
2393     }
2394     default:
2395       break;
2396   }
2397
2398   return result;
2399 }
2400
2401 static void
2402 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2403 {
2404   /* counts as header data */
2405   qtdemux->header_size += length;
2406
2407   /* only consider at least a sufficiently complete ftyp atom */
2408   if (length >= 20) {
2409     GstBuffer *buf;
2410
2411     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2412     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2413         GST_FOURCC_ARGS (qtdemux->major_brand));
2414     if (qtdemux->comp_brands)
2415       gst_buffer_unref (qtdemux->comp_brands);
2416     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2417     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2418   }
2419 }
2420
2421 static void
2422 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2423     GstTagList * xmptaglist)
2424 {
2425   /* Strip out bogus fields */
2426   if (xmptaglist) {
2427     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2428       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2429       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2430     } else {
2431       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2432     }
2433
2434     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2435
2436     /* prioritize native tags using _KEEP mode */
2437     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2438     gst_tag_list_unref (xmptaglist);
2439   }
2440 }
2441
2442 static void
2443 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2444 {
2445   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2446     0x97, 0xA9, 0x42, 0xE8,
2447     0x9C, 0x71, 0x99, 0x94,
2448     0x91, 0xE3, 0xAF, 0xAC
2449   };
2450   static const guint8 playready_uuid[] = {
2451     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2452     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2453   };
2454   guint offset;
2455
2456   /* counts as header data */
2457   qtdemux->header_size += length;
2458
2459   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2460
2461   if (length <= offset + 16) {
2462     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2463     return;
2464   }
2465
2466   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2467     GstBuffer *buf;
2468     GstTagList *taglist;
2469
2470     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2471         length - offset - 16, NULL);
2472     taglist = gst_tag_list_from_xmp_buffer (buf);
2473     gst_buffer_unref (buf);
2474
2475     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2476
2477   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2478     int len;
2479     const gunichar2 *s_utf16;
2480     char *contents;
2481
2482     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2483     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2484     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2485     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2486
2487     g_free (contents);
2488
2489     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2490         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2491         (NULL));
2492   } else {
2493     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2494         GST_READ_UINT32_LE (buffer + offset),
2495         GST_READ_UINT32_LE (buffer + offset + 4),
2496         GST_READ_UINT32_LE (buffer + offset + 8),
2497         GST_READ_UINT32_LE (buffer + offset + 12));
2498   }
2499 }
2500
2501 static void
2502 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2503 {
2504   GstSidxParser sidx_parser;
2505   GstIsoffParserResult res;
2506   guint consumed;
2507
2508   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2509
2510   res =
2511       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2512       &consumed);
2513   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2514   if (res == GST_ISOFF_QT_PARSER_DONE) {
2515     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2516   }
2517   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2518 }
2519
2520 /* caller verifies at least 8 bytes in buf */
2521 static void
2522 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2523     guint64 * plength, guint32 * pfourcc)
2524 {
2525   guint64 length;
2526   guint32 fourcc;
2527
2528   length = QT_UINT32 (data);
2529   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2530   fourcc = QT_FOURCC (data + 4);
2531   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2532
2533   if (length == 0) {
2534     length = G_MAXUINT64;
2535   } else if (length == 1 && size >= 16) {
2536     /* this means we have an extended size, which is the 64 bit value of
2537      * the next 8 bytes */
2538     length = QT_UINT64 (data + 8);
2539     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2540   }
2541
2542   if (plength)
2543     *plength = length;
2544   if (pfourcc)
2545     *pfourcc = fourcc;
2546 }
2547
2548 static gboolean
2549 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2550 {
2551   guint32 version = 0;
2552   GstClockTime duration = 0;
2553
2554   if (!gst_byte_reader_get_uint32_be (br, &version))
2555     goto failed;
2556
2557   version >>= 24;
2558   if (version == 1) {
2559     if (!gst_byte_reader_get_uint64_be (br, &duration))
2560       goto failed;
2561   } else {
2562     guint32 dur = 0;
2563
2564     if (!gst_byte_reader_get_uint32_be (br, &dur))
2565       goto failed;
2566     duration = dur;
2567   }
2568
2569   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2570   qtdemux->duration = duration;
2571
2572   return TRUE;
2573
2574 failed:
2575   {
2576     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2577     return FALSE;
2578   }
2579 }
2580
2581 static gboolean
2582 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2583     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2584 {
2585   if (!stream->parsed_trex && qtdemux->moov_node) {
2586     GNode *mvex, *trex;
2587     GstByteReader trex_data;
2588
2589     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2590     if (mvex) {
2591       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2592           &trex_data);
2593       while (trex) {
2594         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2595
2596         /* skip version/flags */
2597         if (!gst_byte_reader_skip (&trex_data, 4))
2598           goto next;
2599         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2600           goto next;
2601         if (id != stream->track_id)
2602           goto next;
2603         /* sample description index; ignore */
2604         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2605           goto next;
2606         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2607           goto next;
2608         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2609           goto next;
2610         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2611           goto next;
2612
2613         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2614             "duration %d,  size %d, flags 0x%x", stream->track_id,
2615             dur, size, flags);
2616
2617         stream->parsed_trex = TRUE;
2618         stream->def_sample_duration = dur;
2619         stream->def_sample_size = size;
2620         stream->def_sample_flags = flags;
2621
2622       next:
2623         /* iterate all siblings */
2624         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2625             &trex_data);
2626       }
2627     }
2628   }
2629
2630   *ds_duration = stream->def_sample_duration;
2631   *ds_size = stream->def_sample_size;
2632   *ds_flags = stream->def_sample_flags;
2633
2634   /* even then, above values are better than random ... */
2635   if (G_UNLIKELY (!stream->parsed_trex)) {
2636     GST_WARNING_OBJECT (qtdemux,
2637         "failed to find fragment defaults for stream %d", stream->track_id);
2638     return FALSE;
2639   }
2640
2641   return TRUE;
2642 }
2643
2644 /* This method should be called whenever a more accurate duration might
2645  * have been found. It will update all relevant variables if/where needed
2646  */
2647 static void
2648 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2649 {
2650   guint i;
2651   guint64 movdur;
2652   GstClockTime prevdur;
2653
2654   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2655
2656   if (movdur > qtdemux->duration) {
2657     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2658     GST_DEBUG_OBJECT (qtdemux,
2659         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2660         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2661     qtdemux->duration = movdur;
2662     GST_DEBUG_OBJECT (qtdemux,
2663         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2664         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2665         GST_TIME_ARGS (qtdemux->segment.stop));
2666     if (qtdemux->segment.duration == prevdur) {
2667       /* If the current segment has duration/stop identical to previous duration
2668        * update them also (because they were set at that point in time with
2669        * the wrong duration */
2670       /* We convert the value *from* the timescale version to avoid rounding errors */
2671       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2672       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2673       qtdemux->segment.duration = fixeddur;
2674       qtdemux->segment.stop = fixeddur;
2675     }
2676   }
2677   for (i = 0; i < qtdemux->n_streams; i++) {
2678     QtDemuxStream *stream = qtdemux->streams[i];
2679     if (stream) {
2680       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2681       if (movdur > stream->duration) {
2682         GST_DEBUG_OBJECT (qtdemux,
2683             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2684             GST_TIME_ARGS (duration));
2685         stream->duration = movdur;
2686         if (stream->dummy_segment) {
2687           /* Update all dummy values to new duration */
2688           stream->segments[0].stop_time = duration;
2689           stream->segments[0].duration = duration;
2690           stream->segments[0].media_stop = duration;
2691         }
2692       }
2693     }
2694   }
2695 }
2696
2697 static gboolean
2698 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2699     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2700     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2701     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2702 {
2703   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2704   guint64 timestamp;
2705   gint32 data_offset = 0;
2706   guint32 flags = 0, first_flags = 0, samples_count = 0;
2707   gint i;
2708   guint8 *data;
2709   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2710   QtDemuxSample *sample;
2711   gboolean ismv = FALSE;
2712
2713   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2714       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2715       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2716       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2717
2718   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2719     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2720     return TRUE;
2721   }
2722
2723   /* presence of stss or not can't really tell us much,
2724    * and flags and so on tend to be marginally reliable in these files */
2725   if (stream->subtype == FOURCC_soun) {
2726     GST_DEBUG_OBJECT (qtdemux,
2727         "sound track in fragmented file; marking all keyframes");
2728     stream->all_keyframe = TRUE;
2729   }
2730
2731   if (!gst_byte_reader_skip (trun, 1) ||
2732       !gst_byte_reader_get_uint24_be (trun, &flags))
2733     goto fail;
2734
2735   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2736     goto fail;
2737
2738   if (flags & TR_DATA_OFFSET) {
2739     /* note this is really signed */
2740     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
2741       goto fail;
2742     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
2743     /* default base offset = first byte of moof */
2744     if (*base_offset == -1) {
2745       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
2746       *base_offset = moof_offset;
2747     }
2748     *running_offset = *base_offset + data_offset;
2749   } else {
2750     /* if no offset at all, that would mean data starts at moof start,
2751      * which is a bit wrong and is ismv crappy way, so compensate
2752      * assuming data is in mdat following moof */
2753     if (*base_offset == -1) {
2754       *base_offset = moof_offset + moof_length + 8;
2755       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
2756       ismv = TRUE;
2757     }
2758     if (*running_offset == -1)
2759       *running_offset = *base_offset;
2760   }
2761
2762   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
2763       *running_offset);
2764   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
2765       data_offset, flags, samples_count);
2766
2767   if (flags & TR_FIRST_SAMPLE_FLAGS) {
2768     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
2769       GST_DEBUG_OBJECT (qtdemux,
2770           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
2771       flags ^= TR_FIRST_SAMPLE_FLAGS;
2772     } else {
2773       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
2774         goto fail;
2775       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
2776     }
2777   }
2778
2779   /* FIXME ? spec says other bits should also be checked to determine
2780    * entry size (and prefix size for that matter) */
2781   entry_size = 0;
2782   dur_offset = size_offset = 0;
2783   if (flags & TR_SAMPLE_DURATION) {
2784     GST_LOG_OBJECT (qtdemux, "entry duration present");
2785     dur_offset = entry_size;
2786     entry_size += 4;
2787   }
2788   if (flags & TR_SAMPLE_SIZE) {
2789     GST_LOG_OBJECT (qtdemux, "entry size present");
2790     size_offset = entry_size;
2791     entry_size += 4;
2792   }
2793   if (flags & TR_SAMPLE_FLAGS) {
2794     GST_LOG_OBJECT (qtdemux, "entry flags present");
2795     flags_offset = entry_size;
2796     entry_size += 4;
2797   }
2798   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2799     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
2800     ct_offset = entry_size;
2801     entry_size += 4;
2802   }
2803
2804   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
2805     goto fail;
2806   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
2807
2808   if (stream->n_samples + samples_count >=
2809       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
2810     goto index_too_big;
2811
2812   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
2813       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
2814       (stream->n_samples + samples_count) *
2815       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
2816
2817   /* create a new array of samples if it's the first sample parsed */
2818   if (stream->n_samples == 0) {
2819     g_assert (stream->samples == NULL);
2820     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
2821     /* or try to reallocate it with space enough to insert the new samples */
2822   } else
2823     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
2824         stream->n_samples + samples_count);
2825   if (stream->samples == NULL)
2826     goto out_of_memory;
2827
2828   if (qtdemux->fragment_start != -1) {
2829     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
2830     qtdemux->fragment_start = -1;
2831   } else {
2832     if (stream->n_samples == 0) {
2833       if (decode_ts > 0) {
2834         timestamp = decode_ts;
2835       } else if (stream->pending_seek != NULL) {
2836         /* if we don't have a timestamp from a tfdt box, we'll use the one
2837          * from the mfra seek table */
2838         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
2839             GST_TIME_ARGS (stream->pending_seek->ts));
2840
2841         /* FIXME: this is not fully correct, the timestamp refers to the random
2842          * access sample refered to in the tfra entry, which may not necessarily
2843          * be the first sample in the tfrag/trun (but hopefully/usually is) */
2844         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
2845       } else {
2846         timestamp = 0;
2847       }
2848
2849       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2850       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
2851           GST_TIME_ARGS (gst_ts));
2852     } else {
2853       /* subsequent fragments extend stream */
2854       timestamp =
2855           stream->samples[stream->n_samples - 1].timestamp +
2856           stream->samples[stream->n_samples - 1].duration;
2857
2858       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2859       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
2860           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
2861     }
2862   }
2863
2864   sample = stream->samples + stream->n_samples;
2865   for (i = 0; i < samples_count; i++) {
2866     guint32 dur, size, sflags, ct;
2867
2868     /* first read sample data */
2869     if (flags & TR_SAMPLE_DURATION) {
2870       dur = QT_UINT32 (data + dur_offset);
2871     } else {
2872       dur = d_sample_duration;
2873     }
2874     if (flags & TR_SAMPLE_SIZE) {
2875       size = QT_UINT32 (data + size_offset);
2876     } else {
2877       size = d_sample_size;
2878     }
2879     if (flags & TR_FIRST_SAMPLE_FLAGS) {
2880       if (i == 0) {
2881         sflags = first_flags;
2882       } else {
2883         sflags = d_sample_flags;
2884       }
2885     } else if (flags & TR_SAMPLE_FLAGS) {
2886       sflags = QT_UINT32 (data + flags_offset);
2887     } else {
2888       sflags = d_sample_flags;
2889     }
2890     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2891       ct = QT_UINT32 (data + ct_offset);
2892     } else {
2893       ct = 0;
2894     }
2895     data += entry_size;
2896
2897     /* fill the sample information */
2898     sample->offset = *running_offset;
2899     sample->pts_offset = ct;
2900     sample->size = size;
2901     sample->timestamp = timestamp;
2902     sample->duration = dur;
2903     /* sample-is-difference-sample */
2904     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
2905      * now idea how it relates to bitfield other than massive LE/BE confusion */
2906     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
2907     *running_offset += size;
2908     timestamp += dur;
2909     stream->duration_moof += dur;
2910     sample++;
2911   }
2912
2913   /* Update total duration if needed */
2914   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
2915
2916   stream->n_samples += samples_count;
2917   stream->n_samples_moof += samples_count;
2918
2919   if (stream->pending_seek != NULL)
2920     stream->pending_seek = NULL;
2921
2922   return TRUE;
2923
2924 fail:
2925   {
2926     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
2927     return FALSE;
2928   }
2929 out_of_memory:
2930   {
2931     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
2932         stream->n_samples);
2933     return FALSE;
2934   }
2935 index_too_big:
2936   {
2937     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
2938         "be larger than %uMB (broken file?)", stream->n_samples,
2939         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
2940     return FALSE;
2941   }
2942 }
2943
2944 /* find stream with @id */
2945 static inline QtDemuxStream *
2946 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
2947 {
2948   QtDemuxStream *stream;
2949   gint i;
2950
2951   /* check */
2952   if (G_UNLIKELY (!id)) {
2953     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
2954     return NULL;
2955   }
2956
2957   /* try to get it fast and simple */
2958   if (G_LIKELY (id <= qtdemux->n_streams)) {
2959     stream = qtdemux->streams[id - 1];
2960     if (G_LIKELY (stream->track_id == id))
2961       return stream;
2962   }
2963
2964   /* linear search otherwise */
2965   for (i = 0; i < qtdemux->n_streams; i++) {
2966     stream = qtdemux->streams[i];
2967     if (stream->track_id == id)
2968       return stream;
2969   }
2970   if (qtdemux->mss_mode) {
2971     /* mss should have only 1 stream anyway */
2972     return qtdemux->streams[0];
2973   }
2974
2975   return NULL;
2976 }
2977
2978 static gboolean
2979 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
2980     guint32 * fragment_number)
2981 {
2982   if (!gst_byte_reader_skip (mfhd, 4))
2983     goto fail;
2984   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
2985     goto fail;
2986   return TRUE;
2987 fail:
2988   {
2989     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
2990     return FALSE;
2991   }
2992 }
2993
2994 static gboolean
2995 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
2996     QtDemuxStream ** stream, guint32 * default_sample_duration,
2997     guint32 * default_sample_size, guint32 * default_sample_flags,
2998     gint64 * base_offset)
2999 {
3000   guint32 flags = 0;
3001   guint32 track_id = 0;
3002
3003   if (!gst_byte_reader_skip (tfhd, 1) ||
3004       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3005     goto invalid_track;
3006
3007   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3008     goto invalid_track;
3009
3010   *stream = qtdemux_find_stream (qtdemux, track_id);
3011   if (G_UNLIKELY (!*stream))
3012     goto unknown_stream;
3013
3014   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3015     *base_offset = qtdemux->moof_offset;
3016
3017   if (flags & TF_BASE_DATA_OFFSET)
3018     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3019       goto invalid_track;
3020
3021   /* obtain stream defaults */
3022   qtdemux_parse_trex (qtdemux, *stream,
3023       default_sample_duration, default_sample_size, default_sample_flags);
3024
3025   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3026   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3027     if (!gst_byte_reader_skip (tfhd, 4))
3028       goto invalid_track;
3029
3030   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3031     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3032       goto invalid_track;
3033
3034   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3035     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3036       goto invalid_track;
3037
3038   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3039     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3040       goto invalid_track;
3041
3042   return TRUE;
3043
3044 invalid_track:
3045   {
3046     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3047     return FALSE;
3048   }
3049 unknown_stream:
3050   {
3051     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3052     return TRUE;
3053   }
3054 }
3055
3056 static gboolean
3057 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3058     guint64 * decode_time)
3059 {
3060   guint32 version = 0;
3061
3062   if (!gst_byte_reader_get_uint32_be (br, &version))
3063     return FALSE;
3064
3065   version >>= 24;
3066   if (version == 1) {
3067     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3068       goto failed;
3069   } else {
3070     guint32 dec_time = 0;
3071     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3072       goto failed;
3073     *decode_time = dec_time;
3074   }
3075
3076   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3077       *decode_time);
3078
3079   return TRUE;
3080
3081 failed:
3082   {
3083     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3084     return FALSE;
3085   }
3086 }
3087
3088 /* Returns a pointer to a GstStructure containing the properties of
3089  * the stream sample identified by @sample_index. The caller must unref
3090  * the returned object after use. Returns NULL if unsuccessful. */
3091 static GstStructure *
3092 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3093     QtDemuxStream * stream, guint sample_index)
3094 {
3095   QtDemuxCencSampleSetInfo *info = NULL;
3096
3097   g_return_val_if_fail (stream != NULL, NULL);
3098   g_return_val_if_fail (stream->protected, NULL);
3099   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3100
3101   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3102
3103   /* Currently, cenc properties for groups of samples are not supported, so
3104    * simply return a copy of the default sample properties */
3105   return gst_structure_copy (info->default_properties);
3106 }
3107
3108 /* Parses the sizes of sample auxiliary information contained within a stream,
3109  * as given in a saiz box. Returns array of sample_count guint8 size values,
3110  * or NULL on failure */
3111 static guint8 *
3112 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3113     GstByteReader * br, guint32 * sample_count)
3114 {
3115   guint32 flags = 0;
3116   guint8 *info_sizes;
3117   guint8 default_info_size;
3118
3119   g_return_val_if_fail (qtdemux != NULL, NULL);
3120   g_return_val_if_fail (stream != NULL, NULL);
3121   g_return_val_if_fail (br != NULL, NULL);
3122   g_return_val_if_fail (sample_count != NULL, NULL);
3123
3124   if (!gst_byte_reader_get_uint32_be (br, &flags))
3125     return NULL;
3126
3127   if (flags & 0x1) {
3128     /* aux_info_type and aux_info_type_parameter are ignored */
3129     if (!gst_byte_reader_skip (br, 8))
3130       return NULL;
3131   }
3132
3133   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3134     return NULL;
3135   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3136
3137   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3138     return NULL;
3139   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3140
3141
3142   if (default_info_size == 0) {
3143     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3144       return NULL;
3145     }
3146   } else {
3147     info_sizes = g_new (guint8, *sample_count);
3148     memset (info_sizes, default_info_size, *sample_count);
3149   }
3150
3151   return info_sizes;
3152 }
3153
3154 /* Parses the offset of sample auxiliary information contained within a stream,
3155  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3156 static gboolean
3157 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3158     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3159     guint64 * offset)
3160 {
3161   guint8 version = 0;
3162   guint32 flags = 0;
3163   guint32 aux_info_type = 0;
3164   guint32 aux_info_type_parameter = 0;
3165   guint32 entry_count;
3166   guint32 off_32;
3167   guint64 off_64;
3168
3169   g_return_val_if_fail (qtdemux != NULL, FALSE);
3170   g_return_val_if_fail (stream != NULL, FALSE);
3171   g_return_val_if_fail (br != NULL, FALSE);
3172   g_return_val_if_fail (offset != NULL, FALSE);
3173
3174   if (!gst_byte_reader_get_uint8 (br, &version))
3175     return FALSE;
3176
3177   if (!gst_byte_reader_get_uint24_be (br, &flags))
3178     return FALSE;
3179
3180   if (flags & 0x1) {
3181     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type))
3182       return FALSE;
3183     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3184       return FALSE;
3185   } else if (stream->protected) {
3186     aux_info_type = stream->protection_scheme_type;
3187   } else {
3188     aux_info_type = stream->fourcc;
3189   }
3190
3191   if (info_type)
3192     *info_type = aux_info_type;
3193   if (info_type_parameter)
3194     *info_type_parameter = aux_info_type_parameter;
3195
3196   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3197       "aux_info_type_parameter:  %#06x",
3198       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3199
3200   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3201     return FALSE;
3202
3203   if (entry_count != 1) {
3204     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3205     return FALSE;
3206   }
3207
3208   if (version == 0) {
3209     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3210       return FALSE;
3211     *offset = (guint64) off_32;
3212   } else {
3213     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3214       return FALSE;
3215     *offset = off_64;
3216   }
3217
3218   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3219   return TRUE;
3220 }
3221
3222 static void
3223 qtdemux_gst_structure_free (GstStructure * gststructure)
3224 {
3225   if (gststructure) {
3226     gst_structure_free (gststructure);
3227   }
3228 }
3229
3230 /* Parses auxiliary information relating to samples protected using Common
3231  * Encryption (cenc); the format of this information is defined in
3232  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3233 static gboolean
3234 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3235     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3236 {
3237   QtDemuxCencSampleSetInfo *ss_info = NULL;
3238   guint8 size;
3239   gint i;
3240
3241   g_return_val_if_fail (qtdemux != NULL, FALSE);
3242   g_return_val_if_fail (stream != NULL, FALSE);
3243   g_return_val_if_fail (br != NULL, FALSE);
3244   g_return_val_if_fail (stream->protected, FALSE);
3245   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3246
3247   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3248
3249   if (ss_info->crypto_info) {
3250     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3251     g_ptr_array_free (ss_info->crypto_info, TRUE);
3252   }
3253
3254   ss_info->crypto_info =
3255       g_ptr_array_new_full (sample_count,
3256       (GDestroyNotify) qtdemux_gst_structure_free);
3257
3258   for (i = 0; i < sample_count; ++i) {
3259     GstStructure *properties;
3260     guint16 n_subsamples = 0;
3261     guint8 *data;
3262     guint iv_size;
3263     GstBuffer *buf;
3264
3265     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3266     if (properties == NULL) {
3267       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3268       return FALSE;
3269     }
3270     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3271       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3272       gst_structure_free (properties);
3273       return FALSE;
3274     }
3275     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3276       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3277       gst_structure_free (properties);
3278       return FALSE;
3279     }
3280     buf = gst_buffer_new_wrapped (data, iv_size);
3281     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3282     size = info_sizes[i];
3283     if (size > iv_size) {
3284       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3285           || !(n_subsamples > 0)) {
3286         gst_structure_free (properties);
3287         GST_ERROR_OBJECT (qtdemux,
3288             "failed to get subsample count for sample %u", i);
3289         return FALSE;
3290       }
3291       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3292       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3293         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3294             i);
3295         gst_structure_free (properties);
3296         return FALSE;
3297       }
3298       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3299       if (!buf) {
3300         gst_structure_free (properties);
3301         return FALSE;
3302       }
3303       gst_structure_set (properties,
3304           "subsample_count", G_TYPE_UINT, n_subsamples,
3305           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3306     } else {
3307       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3308     }
3309     g_ptr_array_add (ss_info->crypto_info, properties);
3310   }
3311   return TRUE;
3312 }
3313
3314 /* Converts a UUID in raw byte form to a string representation, as defined in
3315  * RFC 4122. The caller takes ownership of the returned string and is
3316  * responsible for freeing it after use. */
3317 static gchar *
3318 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3319 {
3320   const guint8 *uuid = (const guint8 *) uuid_bytes;
3321
3322   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3323       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3324       uuid[0], uuid[1], uuid[2], uuid[3],
3325       uuid[4], uuid[5], uuid[6], uuid[7],
3326       uuid[8], uuid[9], uuid[10], uuid[11],
3327       uuid[12], uuid[13], uuid[14], uuid[15]);
3328 }
3329
3330 /* Parses a Protection System Specific Header box (pssh), as defined in the
3331  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3332  * information needed by a specific content protection system in order to
3333  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3334  * otherwise. */
3335 static gboolean
3336 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3337 {
3338   gchar *sysid_string;
3339   guint32 pssh_size = QT_UINT32 (node->data);
3340   GstBuffer *pssh = NULL;
3341   GstEvent *event = NULL;
3342   guint32 parent_box_type;
3343   gint i;
3344
3345   if (G_UNLIKELY (pssh_size < 32U)) {
3346     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3347     return FALSE;
3348   }
3349
3350   sysid_string =
3351       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3352
3353   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3354
3355   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3356   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3357       gst_buffer_get_size (pssh));
3358
3359   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3360
3361   /* Push an event containing the pssh box onto the queues of all streams. */
3362   event = gst_event_new_protection (sysid_string, pssh,
3363       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3364   for (i = 0; i < qtdemux->n_streams; ++i) {
3365     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3366         gst_event_ref (event));
3367   }
3368   g_free (sysid_string);
3369   gst_event_unref (event);
3370   gst_buffer_unref (pssh);
3371   return TRUE;
3372 }
3373
3374 static gboolean
3375 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3376     guint64 moof_offset, QtDemuxStream * stream)
3377 {
3378   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3379   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3380   GNode *saiz_node, *saio_node, *pssh_node;
3381   GstByteReader saiz_data, saio_data;
3382   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3383   gint64 base_offset, running_offset;
3384   guint32 frag_num;
3385
3386   /* NOTE @stream ignored */
3387
3388   moof_node = g_node_new ((guint8 *) buffer);
3389   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3390   qtdemux_node_dump (qtdemux, moof_node);
3391
3392   /* Get fragment number from mfhd and check it's valid */
3393   mfhd_node =
3394       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3395   if (mfhd_node == NULL)
3396     goto missing_mfhd;
3397   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3398     goto fail;
3399   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3400
3401   /* unknown base_offset to start with */
3402   base_offset = running_offset = -1;
3403   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3404   while (traf_node) {
3405     guint64 decode_time = 0;
3406
3407     /* Fragment Header node */
3408     tfhd_node =
3409         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3410         &tfhd_data);
3411     if (!tfhd_node)
3412       goto missing_tfhd;
3413     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3414             &ds_size, &ds_flags, &base_offset))
3415       goto missing_tfhd;
3416
3417     /* The following code assumes at most a single set of sample auxiliary
3418      * data in the fragment (consisting of a saiz box and a corresponding saio
3419      * box); in theory, however, there could be multiple sets of sample
3420      * auxiliary data in a fragment. */
3421     saiz_node =
3422         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3423         &saiz_data);
3424     if (saiz_node) {
3425       guint32 info_type = 0;
3426       guint64 offset = 0;
3427       guint32 info_type_parameter = 0;
3428
3429       g_free (qtdemux->cenc_aux_info_sizes);
3430
3431       qtdemux->cenc_aux_info_sizes =
3432           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3433           &qtdemux->cenc_aux_sample_count);
3434       if (qtdemux->cenc_aux_info_sizes == NULL) {
3435         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3436         goto fail;
3437       }
3438       saio_node =
3439           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3440           &saio_data);
3441       if (!saio_node) {
3442         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3443         g_free (qtdemux->cenc_aux_info_sizes);
3444         qtdemux->cenc_aux_info_sizes = NULL;
3445         goto fail;
3446       }
3447
3448       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3449                   &info_type, &info_type_parameter, &offset))) {
3450         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3451         g_free (qtdemux->cenc_aux_info_sizes);
3452         qtdemux->cenc_aux_info_sizes = NULL;
3453         goto fail;
3454       }
3455       if (base_offset > qtdemux->moof_offset)
3456         offset += (guint64) (base_offset - qtdemux->moof_offset);
3457       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3458         GstByteReader br;
3459         if (offset > length) {
3460           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3461           qtdemux->cenc_aux_info_offset = offset;
3462         } else {
3463           gst_byte_reader_init (&br, buffer + offset, length - offset);
3464           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3465                   qtdemux->cenc_aux_info_sizes,
3466                   qtdemux->cenc_aux_sample_count)) {
3467             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3468             g_free (qtdemux->cenc_aux_info_sizes);
3469             qtdemux->cenc_aux_info_sizes = NULL;
3470             goto fail;
3471           }
3472         }
3473       }
3474     }
3475
3476     tfdt_node =
3477         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3478         &tfdt_data);
3479     if (tfdt_node) {
3480       GstClockTime decode_time_ts;
3481
3482       /* We'll use decode_time to interpolate timestamps
3483        * in case the input timestamps are missing */
3484       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3485
3486       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3487
3488       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3489           " (%" GST_TIME_FORMAT ")", decode_time,
3490           GST_TIME_ARGS (decode_time_ts));
3491
3492       /* Discard the fragment buffer timestamp info to avoid using it.
3493        * Rely on tfdt instead as it is more accurate than the timestamp
3494        * that is fetched from a manifest/playlist and is usually
3495        * less accurate. */
3496       qtdemux->fragment_start = -1;
3497     }
3498
3499     if (G_UNLIKELY (!stream)) {
3500       /* we lost track of offset, we'll need to regain it,
3501        * but can delay complaining until later or avoid doing so altogether */
3502       base_offset = -2;
3503       goto next;
3504     }
3505     if (G_UNLIKELY (base_offset < -1))
3506       goto lost_offset;
3507
3508     if (qtdemux->upstream_format_is_time)
3509       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3510
3511     /* initialise moof sample data */
3512     stream->n_samples_moof = 0;
3513     stream->duration_moof = 0;
3514
3515     /* Track Run node */
3516     trun_node =
3517         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3518         &trun_data);
3519     while (trun_node) {
3520       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3521           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3522           &running_offset, decode_time);
3523       /* iterate all siblings */
3524       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3525           &trun_data);
3526     }
3527     /* if no new base_offset provided for next traf,
3528      * base is end of current traf */
3529     base_offset = running_offset;
3530     running_offset = -1;
3531
3532     if (stream->n_samples_moof && stream->duration_moof)
3533       stream->new_caps = TRUE;
3534
3535   next:
3536     /* iterate all siblings */
3537     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3538   }
3539
3540   /* parse any protection system info */
3541   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3542   while (pssh_node) {
3543     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3544     qtdemux_parse_pssh (qtdemux, pssh_node);
3545     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3546   }
3547
3548   g_node_destroy (moof_node);
3549   return TRUE;
3550
3551 missing_tfhd:
3552   {
3553     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3554     goto fail;
3555   }
3556 missing_mfhd:
3557   {
3558     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3559     goto fail;
3560   }
3561 lost_offset:
3562   {
3563     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3564     goto fail;
3565   }
3566 fail:
3567   {
3568     g_node_destroy (moof_node);
3569     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3570         (_("This file is corrupt and cannot be played.")), (NULL));
3571     return FALSE;
3572   }
3573 }
3574
3575 #if 0
3576 /* might be used if some day we actually use mfra & co
3577  * for random access to fragments,
3578  * but that will require quite some modifications and much less relying
3579  * on a sample array */
3580 #endif
3581
3582 static gboolean
3583 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3584 {
3585   QtDemuxStream *stream;
3586   guint32 ver_flags, track_id, len, num_entries, i;
3587   guint value_size, traf_size, trun_size, sample_size;
3588   guint64 time = 0, moof_offset = 0;
3589 #if 0
3590   GstBuffer *buf = NULL;
3591   GstFlowReturn ret;
3592 #endif
3593   GstByteReader tfra;
3594
3595   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3596
3597   if (!gst_byte_reader_skip (&tfra, 8))
3598     return FALSE;
3599
3600   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3601     return FALSE;
3602
3603   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3604       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3605       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3606     return FALSE;
3607
3608   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3609
3610   stream = qtdemux_find_stream (qtdemux, track_id);
3611   if (stream == NULL)
3612     goto unknown_trackid;
3613
3614   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3615   sample_size = (len & 3) + 1;
3616   trun_size = ((len & 12) >> 2) + 1;
3617   traf_size = ((len & 48) >> 4) + 1;
3618
3619   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3620       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3621
3622   if (num_entries == 0)
3623     goto no_samples;
3624
3625   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3626           value_size + value_size + traf_size + trun_size + sample_size))
3627     goto corrupt_file;
3628
3629   g_free (stream->ra_entries);
3630   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3631   stream->n_ra_entries = num_entries;
3632
3633   for (i = 0; i < num_entries; i++) {
3634     qt_atom_parser_get_offset (&tfra, value_size, &time);
3635     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3636     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3637     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3638     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3639
3640     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3641
3642     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3643         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3644
3645     stream->ra_entries[i].ts = time;
3646     stream->ra_entries[i].moof_offset = moof_offset;
3647
3648     /* don't want to go through the entire file and read all moofs at startup */
3649 #if 0
3650     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3651     if (ret != GST_FLOW_OK)
3652       goto corrupt_file;
3653     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3654         moof_offset, stream);
3655     gst_buffer_unref (buf);
3656 #endif
3657   }
3658
3659   check_update_duration (qtdemux, time);
3660
3661   return TRUE;
3662
3663 /* ERRORS */
3664 unknown_trackid:
3665   {
3666     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3667     return FALSE;
3668   }
3669 corrupt_file:
3670   {
3671     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3672     return FALSE;
3673   }
3674 no_samples:
3675   {
3676     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3677     return FALSE;
3678   }
3679 }
3680
3681 static gboolean
3682 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3683 {
3684   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3685   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3686   GstBuffer *mfro = NULL, *mfra = NULL;
3687   GstFlowReturn flow;
3688   gboolean ret = FALSE;
3689   GNode *mfra_node, *tfra_node;
3690   guint64 mfra_offset = 0;
3691   guint32 fourcc, mfra_size;
3692   gint64 len;
3693
3694   /* query upstream size in bytes */
3695   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3696     goto size_query_failed;
3697
3698   /* mfro box should be at the very end of the file */
3699   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3700   if (flow != GST_FLOW_OK)
3701     goto exit;
3702
3703   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3704
3705   fourcc = QT_FOURCC (mfro_map.data + 4);
3706   if (fourcc != FOURCC_mfro)
3707     goto exit;
3708
3709   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3710   if (mfro_map.size < 16)
3711     goto invalid_mfro_size;
3712
3713   mfra_size = QT_UINT32 (mfro_map.data + 12);
3714   if (mfra_size >= len)
3715     goto invalid_mfra_size;
3716
3717   mfra_offset = len - mfra_size;
3718
3719   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3720       mfra_offset, mfra_size);
3721
3722   /* now get and parse mfra box */
3723   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3724   if (flow != GST_FLOW_OK)
3725     goto broken_file;
3726
3727   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
3728
3729   mfra_node = g_node_new ((guint8 *) mfra_map.data);
3730   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
3731
3732   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
3733
3734   while (tfra_node) {
3735     qtdemux_parse_tfra (qtdemux, tfra_node);
3736     /* iterate all siblings */
3737     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
3738   }
3739   g_node_destroy (mfra_node);
3740
3741   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
3742   ret = TRUE;
3743
3744 exit:
3745
3746   if (mfro) {
3747     if (mfro_map.memory != NULL)
3748       gst_buffer_unmap (mfro, &mfro_map);
3749     gst_buffer_unref (mfro);
3750   }
3751   if (mfra) {
3752     if (mfra_map.memory != NULL)
3753       gst_buffer_unmap (mfra, &mfra_map);
3754     gst_buffer_unref (mfra);
3755   }
3756   return ret;
3757
3758 /* ERRORS */
3759 size_query_failed:
3760   {
3761     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
3762     goto exit;
3763   }
3764 invalid_mfro_size:
3765   {
3766     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
3767     goto exit;
3768   }
3769 invalid_mfra_size:
3770   {
3771     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
3772     goto exit;
3773   }
3774 broken_file:
3775   {
3776     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
3777     goto exit;
3778   }
3779 }
3780
3781 static guint64
3782 add_offset (guint64 offset, guint64 advance)
3783 {
3784   /* Avoid 64-bit overflow by clamping */
3785   if (offset > G_MAXUINT64 - advance)
3786     return G_MAXUINT64;
3787   return offset + advance;
3788 }
3789
3790 static GstFlowReturn
3791 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
3792 {
3793   guint64 length = 0;
3794   guint32 fourcc = 0;
3795   GstBuffer *buf = NULL;
3796   GstFlowReturn ret = GST_FLOW_OK;
3797   guint64 cur_offset = qtdemux->offset;
3798   GstMapInfo map;
3799
3800   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
3801   if (G_UNLIKELY (ret != GST_FLOW_OK))
3802     goto beach;
3803   gst_buffer_map (buf, &map, GST_MAP_READ);
3804   if (G_LIKELY (map.size >= 8))
3805     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
3806   gst_buffer_unmap (buf, &map);
3807   gst_buffer_unref (buf);
3808
3809   /* maybe we already got most we needed, so only consider this eof */
3810   if (G_UNLIKELY (length == 0)) {
3811     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
3812         (_("Invalid atom size.")),
3813         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
3814             GST_FOURCC_ARGS (fourcc)));
3815     ret = GST_FLOW_EOS;
3816     goto beach;
3817   }
3818
3819   switch (fourcc) {
3820     case FOURCC_moof:
3821       /* record for later parsing when needed */
3822       if (!qtdemux->moof_offset) {
3823         qtdemux->moof_offset = qtdemux->offset;
3824       }
3825       if (qtdemux_pull_mfro_mfra (qtdemux)) {
3826         /* FIXME */
3827       } else {
3828         qtdemux->offset += length;      /* skip moof and keep going */
3829       }
3830       if (qtdemux->got_moov) {
3831         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
3832         ret = GST_FLOW_EOS;
3833         goto beach;
3834       }
3835       break;
3836     case FOURCC_mdat:
3837     case FOURCC_free:
3838     case FOURCC_wide:
3839     case FOURCC_PICT:
3840     case FOURCC_pnot:
3841     {
3842       GST_LOG_OBJECT (qtdemux,
3843           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
3844           GST_FOURCC_ARGS (fourcc), cur_offset);
3845       qtdemux->offset = add_offset (qtdemux->offset, length);
3846       break;
3847     }
3848     case FOURCC_moov:
3849     {
3850       GstBuffer *moov = NULL;
3851
3852       if (qtdemux->got_moov) {
3853         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
3854         qtdemux->offset = add_offset (qtdemux->offset, length);
3855         goto beach;
3856       }
3857
3858       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
3859       if (ret != GST_FLOW_OK)
3860         goto beach;
3861       gst_buffer_map (moov, &map, GST_MAP_READ);
3862
3863       if (length != map.size) {
3864         /* Some files have a 'moov' atom at the end of the file which contains
3865          * a terminal 'free' atom where the body of the atom is missing.
3866          * Check for, and permit, this special case.
3867          */
3868         if (map.size >= 8) {
3869           guint8 *final_data = map.data + (map.size - 8);
3870           guint32 final_length = QT_UINT32 (final_data);
3871           guint32 final_fourcc = QT_FOURCC (final_data + 4);
3872
3873           if (final_fourcc == FOURCC_free
3874               && map.size + final_length - 8 == length) {
3875             /* Ok, we've found that special case. Allocate a new buffer with
3876              * that free atom actually present. */
3877             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
3878             gst_buffer_fill (newmoov, 0, map.data, map.size);
3879             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
3880             gst_buffer_unmap (moov, &map);
3881             gst_buffer_unref (moov);
3882             moov = newmoov;
3883             gst_buffer_map (moov, &map, GST_MAP_READ);
3884           }
3885         }
3886       }
3887
3888       if (length != map.size) {
3889         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3890             (_("This file is incomplete and cannot be played.")),
3891             ("We got less than expected (received %" G_GSIZE_FORMAT
3892                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
3893                 (guint) length, cur_offset));
3894         gst_buffer_unmap (moov, &map);
3895         gst_buffer_unref (moov);
3896         ret = GST_FLOW_ERROR;
3897         goto beach;
3898       }
3899       qtdemux->offset += length;
3900
3901       qtdemux_parse_moov (qtdemux, map.data, length);
3902       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
3903
3904       qtdemux_parse_tree (qtdemux);
3905       g_node_destroy (qtdemux->moov_node);
3906       gst_buffer_unmap (moov, &map);
3907       gst_buffer_unref (moov);
3908       qtdemux->moov_node = NULL;
3909       qtdemux->got_moov = TRUE;
3910
3911       break;
3912     }
3913     case FOURCC_ftyp:
3914     {
3915       GstBuffer *ftyp = NULL;
3916
3917       /* extract major brand; might come in handy for ISO vs QT issues */
3918       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
3919       if (ret != GST_FLOW_OK)
3920         goto beach;
3921       qtdemux->offset += length;
3922       gst_buffer_map (ftyp, &map, GST_MAP_READ);
3923       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
3924       gst_buffer_unmap (ftyp, &map);
3925       gst_buffer_unref (ftyp);
3926       break;
3927     }
3928     case FOURCC_uuid:
3929     {
3930       GstBuffer *uuid = NULL;
3931
3932       /* uuid are extension atoms */
3933       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
3934       if (ret != GST_FLOW_OK)
3935         goto beach;
3936       qtdemux->offset += length;
3937       gst_buffer_map (uuid, &map, GST_MAP_READ);
3938       qtdemux_parse_uuid (qtdemux, map.data, map.size);
3939       gst_buffer_unmap (uuid, &map);
3940       gst_buffer_unref (uuid);
3941       break;
3942     }
3943     case FOURCC_sidx:
3944     {
3945       GstBuffer *sidx = NULL;
3946       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
3947       if (ret != GST_FLOW_OK)
3948         goto beach;
3949       qtdemux->offset += length;
3950       gst_buffer_map (sidx, &map, GST_MAP_READ);
3951       qtdemux_parse_sidx (qtdemux, map.data, map.size);
3952       gst_buffer_unmap (sidx, &map);
3953       gst_buffer_unref (sidx);
3954       break;
3955     }
3956     default:
3957     {
3958       GstBuffer *unknown = NULL;
3959
3960       GST_LOG_OBJECT (qtdemux,
3961           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
3962           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
3963           cur_offset);
3964       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
3965       if (ret != GST_FLOW_OK)
3966         goto beach;
3967       gst_buffer_map (unknown, &map, GST_MAP_READ);
3968       GST_MEMDUMP ("Unknown tag", map.data, map.size);
3969       gst_buffer_unmap (unknown, &map);
3970       gst_buffer_unref (unknown);
3971       qtdemux->offset += length;
3972       break;
3973     }
3974   }
3975
3976 beach:
3977   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
3978     /* digested all data, show what we have */
3979     qtdemux_prepare_streams (qtdemux);
3980     ret = qtdemux_expose_streams (qtdemux);
3981
3982     qtdemux->state = QTDEMUX_STATE_MOVIE;
3983     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
3984         qtdemux->state);
3985     return ret;
3986   }
3987   return ret;
3988 }
3989
3990 /* Seeks to the previous keyframe of the indexed stream and
3991  * aligns other streams with respect to the keyframe timestamp
3992  * of indexed stream. Only called in case of Reverse Playback
3993  */
3994 static GstFlowReturn
3995 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
3996 {
3997   guint8 n = 0;
3998   guint32 seg_idx = 0, k_index = 0;
3999   guint32 ref_seg_idx, ref_k_index;
4000   GstClockTime k_pos = 0, last_stop = 0;
4001   QtDemuxSegment *seg = NULL;
4002   QtDemuxStream *ref_str = NULL;
4003   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4004   guint64 target_ts;
4005
4006   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4007    * and finally align all the other streams on that timestamp with their
4008    * respective keyframes */
4009   for (n = 0; n < qtdemux->n_streams; n++) {
4010     QtDemuxStream *str = qtdemux->streams[n];
4011
4012     /* No candidate yet, take the first stream */
4013     if (!ref_str) {
4014       ref_str = str;
4015       continue;
4016     }
4017
4018     /* So that stream has a segment, we prefer video streams */
4019     if (str->subtype == FOURCC_vide) {
4020       ref_str = str;
4021       break;
4022     }
4023   }
4024
4025   if (G_UNLIKELY (!ref_str)) {
4026     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4027     goto eos;
4028   }
4029
4030   if (G_UNLIKELY (!ref_str->from_sample)) {
4031     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4032     goto eos;
4033   }
4034
4035   /* So that stream has been playing from from_sample to to_sample. We will
4036    * get the timestamp of the previous sample and search for a keyframe before
4037    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4038   if (ref_str->subtype == FOURCC_vide) {
4039     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4040         ref_str->from_sample - 1);
4041   } else {
4042     if (ref_str->from_sample >= 10)
4043       k_index = ref_str->from_sample - 10;
4044     else
4045       k_index = 0;
4046   }
4047
4048   target_ts =
4049       ref_str->samples[k_index].timestamp +
4050       ref_str->samples[k_index].pts_offset;
4051
4052   /* get current segment for that stream */
4053   seg = &ref_str->segments[ref_str->segment_index];
4054   /* Use segment start in original timescale for comparisons */
4055   seg_media_start_mov = seg->trak_media_start;
4056
4057   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4058       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4059       k_index, target_ts, seg_media_start_mov,
4060       GST_TIME_ARGS (seg->media_start));
4061
4062   /* Crawl back through segments to find the one containing this I frame */
4063   while (target_ts < seg_media_start_mov) {
4064     GST_DEBUG_OBJECT (qtdemux,
4065         "keyframe position (sample %u) is out of segment %u " " target %"
4066         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4067         ref_str->segment_index, target_ts, seg_media_start_mov);
4068
4069     if (G_UNLIKELY (!ref_str->segment_index)) {
4070       /* Reached first segment, let's consider it's EOS */
4071       goto eos;
4072     }
4073     ref_str->segment_index--;
4074     seg = &ref_str->segments[ref_str->segment_index];
4075     /* Use segment start in original timescale for comparisons */
4076     seg_media_start_mov = seg->trak_media_start;
4077   }
4078   /* Calculate time position of the keyframe and where we should stop */
4079   k_pos =
4080       QTSTREAMTIME_TO_GSTTIME (ref_str,
4081       target_ts - seg->trak_media_start) + seg->time;
4082   last_stop =
4083       QTSTREAMTIME_TO_GSTTIME (ref_str,
4084       ref_str->samples[ref_str->from_sample].timestamp -
4085       seg->trak_media_start) + seg->time;
4086
4087   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4088       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4089       k_index, GST_TIME_ARGS (k_pos));
4090
4091   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4092   qtdemux->segment.position = last_stop;
4093   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4094       GST_TIME_ARGS (last_stop));
4095
4096   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4097     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4098     goto eos;
4099   }
4100
4101   ref_seg_idx = ref_str->segment_index;
4102   ref_k_index = k_index;
4103
4104   /* Align them all on this */
4105   for (n = 0; n < qtdemux->n_streams; n++) {
4106     guint32 index = 0;
4107     GstClockTime seg_time = 0;
4108     QtDemuxStream *str = qtdemux->streams[n];
4109
4110     /* aligning reference stream again might lead to backing up to yet another
4111      * keyframe (due to timestamp rounding issues),
4112      * potentially putting more load on downstream; so let's try to avoid */
4113     if (str == ref_str) {
4114       seg_idx = ref_seg_idx;
4115       seg = &str->segments[seg_idx];
4116       k_index = ref_k_index;
4117       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4118           "sample at index %d", n, ref_str->segment_index, k_index);
4119     } else {
4120       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4121       GST_DEBUG_OBJECT (qtdemux,
4122           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4123           seg_idx, GST_TIME_ARGS (k_pos));
4124
4125       /* get segment and time in the segment */
4126       seg = &str->segments[seg_idx];
4127       seg_time = k_pos - seg->time;
4128
4129       /* get the media time in the segment.
4130        * No adjustment for empty "filler" segments */
4131       if (seg->media_start != GST_CLOCK_TIME_NONE)
4132         seg_time += seg->media_start;
4133
4134       /* get the index of the sample with media time */
4135       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4136       GST_DEBUG_OBJECT (qtdemux,
4137           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4138           GST_TIME_ARGS (seg_time), index);
4139
4140       /* find previous keyframe */
4141       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4142     }
4143
4144     /* Remember until where we want to go */
4145     str->to_sample = str->from_sample - 1;
4146     /* Define our time position */
4147     target_ts =
4148         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4149     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4150     if (seg->media_start != GST_CLOCK_TIME_NONE)
4151       str->time_position -= seg->media_start;
4152
4153     /* Now seek back in time */
4154     gst_qtdemux_move_stream (qtdemux, str, k_index);
4155     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4156         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4157         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4158   }
4159
4160   return GST_FLOW_OK;
4161
4162 eos:
4163   return GST_FLOW_EOS;
4164 }
4165
4166 /* activate the given segment number @seg_idx of @stream at time @offset.
4167  * @offset is an absolute global position over all the segments.
4168  *
4169  * This will push out a NEWSEGMENT event with the right values and
4170  * position the stream index to the first decodable sample before
4171  * @offset.
4172  */
4173 static gboolean
4174 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4175     guint32 seg_idx, GstClockTime offset)
4176 {
4177   GstEvent *event;
4178   QtDemuxSegment *segment;
4179   guint32 index, kf_index;
4180   GstClockTime seg_time;
4181   GstClockTime start, stop, time;
4182   gdouble rate;
4183
4184   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4185       seg_idx, GST_TIME_ARGS (offset));
4186
4187   /* update the current segment */
4188   stream->segment_index = seg_idx;
4189
4190   /* get the segment */
4191   segment = &stream->segments[seg_idx];
4192
4193   if (G_UNLIKELY (offset < segment->time)) {
4194     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4195         GST_TIME_ARGS (segment->time));
4196     return FALSE;
4197   }
4198
4199   /* segment lies beyond total indicated duration */
4200   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4201           segment->time > qtdemux->segment.duration)) {
4202     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4203         " < segment->time %" GST_TIME_FORMAT,
4204         GST_TIME_ARGS (qtdemux->segment.duration),
4205         GST_TIME_ARGS (segment->time));
4206     return FALSE;
4207   }
4208
4209   /* get time in this segment */
4210   seg_time = offset - segment->time;
4211
4212   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4213       GST_TIME_ARGS (seg_time));
4214
4215   if (G_UNLIKELY (seg_time > segment->duration)) {
4216     GST_LOG_OBJECT (stream->pad,
4217         "seg_time > segment->duration %" GST_TIME_FORMAT,
4218         GST_TIME_ARGS (segment->duration));
4219     seg_time = segment->duration;
4220   }
4221
4222   /* qtdemux->segment.stop is in outside-time-realm, whereas
4223    * segment->media_stop is in track-time-realm.
4224    *
4225    * In order to compare the two, we need to bring segment.stop
4226    * into the track-time-realm */
4227
4228   stop = qtdemux->segment.stop;
4229   if (stop == GST_CLOCK_TIME_NONE)
4230     stop = qtdemux->segment.duration;
4231   if (stop == GST_CLOCK_TIME_NONE)
4232     stop = segment->media_stop;
4233   else
4234     stop =
4235         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4236
4237   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4238     start = segment->time + seg_time;
4239     time = offset;
4240     stop = start - seg_time + segment->duration;
4241   } else if (qtdemux->segment.rate >= 0) {
4242     start = MIN (segment->media_start + seg_time, stop);
4243     time = offset;
4244   } else {
4245     if (segment->media_start >= qtdemux->segment.start) {
4246       time = segment->time;
4247     } else {
4248       time = segment->time + (qtdemux->segment.start - segment->media_start);
4249     }
4250
4251     start = MAX (segment->media_start, qtdemux->segment.start);
4252     stop = MIN (segment->media_start + seg_time, stop);
4253   }
4254
4255   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4256       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4257       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4258
4259   /* combine global rate with that of the segment */
4260   rate = segment->rate * qtdemux->segment.rate;
4261
4262   /* Copy flags from main segment */
4263   stream->segment.flags = qtdemux->segment.flags;
4264
4265   /* update the segment values used for clipping */
4266   stream->segment.offset = qtdemux->segment.offset;
4267   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4268   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4269   stream->segment.rate = rate;
4270   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4271       stream->cslg_shift);
4272   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4273       stream->cslg_shift);
4274   stream->segment.time = time;
4275   stream->segment.position = stream->segment.start;
4276
4277   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4278       &stream->segment);
4279
4280   /* now prepare and send the segment */
4281   if (stream->pad) {
4282     event = gst_event_new_segment (&stream->segment);
4283     if (stream->segment_seqnum) {
4284       gst_event_set_seqnum (event, stream->segment_seqnum);
4285     }
4286     gst_pad_push_event (stream->pad, event);
4287     /* assume we can send more data now */
4288     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4289     /* clear to send tags on this pad now */
4290     gst_qtdemux_push_tags (qtdemux, stream);
4291   }
4292
4293   /* in the fragmented case, we pick a fragment that starts before our
4294    * desired position and rely on downstream to wait for a keyframe
4295    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4296    * tfra entries tells us which trun/sample the key unit is in, but we don't
4297    * make use of this additional information at the moment) */
4298   if (qtdemux->fragmented) {
4299     stream->to_sample = G_MAXUINT32;
4300     return TRUE;
4301   }
4302
4303   /* We don't need to look for a sample in push-based */
4304   if (!qtdemux->pullbased)
4305     return TRUE;
4306
4307   /* and move to the keyframe before the indicated media time of the
4308    * segment */
4309   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4310     if (qtdemux->segment.rate >= 0) {
4311       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4312       stream->to_sample = G_MAXUINT32;
4313       GST_DEBUG_OBJECT (stream->pad,
4314           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4315           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4316           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4317     } else {
4318       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4319       stream->to_sample = index;
4320       GST_DEBUG_OBJECT (stream->pad,
4321           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4322           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4323           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4324     }
4325   } else {
4326     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4327         "this is an empty segment");
4328     return TRUE;
4329   }
4330
4331   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4332    * encountered an error and printed a message so we return appropriately */
4333   if (index == -1)
4334     return FALSE;
4335
4336   /* we're at the right spot */
4337   if (index == stream->sample_index) {
4338     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4339     return TRUE;
4340   }
4341
4342   /* find keyframe of the target index */
4343   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4344
4345 /* *INDENT-OFF* */
4346 /* indent does stupid stuff with stream->samples[].timestamp */
4347
4348   /* if we move forwards, we don't have to go back to the previous
4349    * keyframe since we already sent that. We can also just jump to
4350    * the keyframe right before the target index if there is one. */
4351   if (index > stream->sample_index) {
4352     /* moving forwards check if we move past a keyframe */
4353     if (kf_index > stream->sample_index) {
4354       GST_DEBUG_OBJECT (stream->pad,
4355            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4356            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4357            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4358       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4359     } else {
4360       GST_DEBUG_OBJECT (stream->pad,
4361           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4362           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4363           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4364     }
4365   } else {
4366     GST_DEBUG_OBJECT (stream->pad,
4367         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4368         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4369         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4370     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4371   }
4372
4373 /* *INDENT-ON* */
4374
4375   return TRUE;
4376 }
4377
4378 /* prepare to get the current sample of @stream, getting essential values.
4379  *
4380  * This function will also prepare and send the segment when needed.
4381  *
4382  * Return FALSE if the stream is EOS.
4383  *
4384  * PULL-BASED
4385  */
4386 static gboolean
4387 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4388     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4389     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4390     gboolean * keyframe)
4391 {
4392   QtDemuxSample *sample;
4393   GstClockTime time_position;
4394   guint32 seg_idx;
4395
4396   g_return_val_if_fail (stream != NULL, FALSE);
4397
4398   time_position = stream->time_position;
4399   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4400     goto eos;
4401
4402   seg_idx = stream->segment_index;
4403   if (G_UNLIKELY (seg_idx == -1)) {
4404     /* find segment corresponding to time_position if we are looking
4405      * for a segment. */
4406     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4407   }
4408
4409   /* different segment, activate it, sample_index will be set. */
4410   if (G_UNLIKELY (stream->segment_index != seg_idx))
4411     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4412
4413   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4414                   segment_index]))) {
4415     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4416
4417     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4418         " prepare empty sample");
4419
4420     *empty = TRUE;
4421     *pts = *dts = time_position;
4422     *duration = seg->duration - (time_position - seg->time);
4423
4424     return TRUE;
4425   }
4426
4427   *empty = FALSE;
4428
4429   if (stream->sample_index == -1)
4430     stream->sample_index = 0;
4431
4432   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4433       stream->sample_index, stream->n_samples);
4434
4435   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4436     if (!qtdemux->fragmented)
4437       goto eos;
4438
4439     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4440     do {
4441       GstFlowReturn flow;
4442
4443       GST_OBJECT_LOCK (qtdemux);
4444       flow = qtdemux_add_fragmented_samples (qtdemux);
4445       GST_OBJECT_UNLOCK (qtdemux);
4446
4447       if (flow != GST_FLOW_OK)
4448         goto eos;
4449     }
4450     while (stream->sample_index >= stream->n_samples);
4451   }
4452
4453   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4454     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4455         stream->sample_index);
4456     return FALSE;
4457   }
4458
4459   /* now get the info for the sample we're at */
4460   sample = &stream->samples[stream->sample_index];
4461
4462   *dts = QTSAMPLE_DTS (stream, sample);
4463   *pts = QTSAMPLE_PTS (stream, sample);
4464   *offset = sample->offset;
4465   *size = sample->size;
4466   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4467   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4468
4469   return TRUE;
4470
4471   /* special cases */
4472 eos:
4473   {
4474     stream->time_position = GST_CLOCK_TIME_NONE;
4475     return FALSE;
4476   }
4477 }
4478
4479 /* move to the next sample in @stream.
4480  *
4481  * Moves to the next segment when needed.
4482  */
4483 static void
4484 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4485 {
4486   QtDemuxSample *sample;
4487   QtDemuxSegment *segment;
4488
4489   /* get current segment */
4490   segment = &stream->segments[stream->segment_index];
4491
4492   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4493     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4494     goto next_segment;
4495   }
4496
4497   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4498     /* Mark the stream as EOS */
4499     GST_DEBUG_OBJECT (qtdemux,
4500         "reached max allowed sample %u, mark EOS", stream->to_sample);
4501     stream->time_position = GST_CLOCK_TIME_NONE;
4502     return;
4503   }
4504
4505   /* move to next sample */
4506   stream->sample_index++;
4507   stream->offset_in_sample = 0;
4508
4509   /* reached the last sample, we need the next segment */
4510   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4511     goto next_segment;
4512
4513   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4514     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4515         stream->sample_index);
4516     return;
4517   }
4518
4519   /* get next sample */
4520   sample = &stream->samples[stream->sample_index];
4521
4522   /* see if we are past the segment */
4523   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4524     goto next_segment;
4525
4526   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4527     /* inside the segment, update time_position, looks very familiar to
4528      * GStreamer segments, doesn't it? */
4529     stream->time_position =
4530         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4531   } else {
4532     /* not yet in segment, time does not yet increment. This means
4533      * that we are still prerolling keyframes to the decoder so it can
4534      * decode the first sample of the segment. */
4535     stream->time_position = segment->time;
4536   }
4537   return;
4538
4539   /* move to the next segment */
4540 next_segment:
4541   {
4542     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4543
4544     if (stream->segment_index == stream->n_segments - 1) {
4545       /* are we at the end of the last segment, we're EOS */
4546       stream->time_position = GST_CLOCK_TIME_NONE;
4547     } else {
4548       /* else we're only at the end of the current segment */
4549       stream->time_position = segment->stop_time;
4550     }
4551     /* make sure we select a new segment */
4552
4553     /* accumulate previous segments */
4554     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4555       stream->accumulated_base +=
4556           (stream->segment.stop -
4557           stream->segment.start) / ABS (stream->segment.rate);
4558
4559     stream->segment_index = -1;
4560   }
4561 }
4562
4563 static void
4564 gst_qtdemux_sync_streams (GstQTDemux * demux)
4565 {
4566   gint i;
4567
4568   if (demux->n_streams <= 1)
4569     return;
4570
4571   for (i = 0; i < demux->n_streams; i++) {
4572     QtDemuxStream *stream;
4573     GstClockTime end_time;
4574
4575     stream = demux->streams[i];
4576
4577     if (!stream->pad)
4578       continue;
4579
4580     /* TODO advance time on subtitle streams here, if any some day */
4581
4582     /* some clips/trailers may have unbalanced streams at the end,
4583      * so send EOS on shorter stream to prevent stalling others */
4584
4585     /* do not mess with EOS if SEGMENT seeking */
4586     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4587       continue;
4588
4589     if (demux->pullbased) {
4590       /* loop mode is sample time based */
4591       if (!STREAM_IS_EOS (stream))
4592         continue;
4593     } else {
4594       /* push mode is byte position based */
4595       if (stream->n_samples &&
4596           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4597         continue;
4598     }
4599
4600     if (stream->sent_eos)
4601       continue;
4602
4603     /* only act if some gap */
4604     end_time = stream->segments[stream->n_segments - 1].stop_time;
4605     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4606         ", stream end: %" GST_TIME_FORMAT,
4607         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4608     if (GST_CLOCK_TIME_IS_VALID (end_time)
4609         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4610       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4611           GST_PAD_NAME (stream->pad));
4612       stream->sent_eos = TRUE;
4613       gst_pad_push_event (stream->pad, gst_event_new_eos ());
4614     }
4615   }
4616 }
4617
4618 /* EOS and NOT_LINKED need to be combined. This means that we return:
4619  *
4620  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4621  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4622  */
4623 static GstFlowReturn
4624 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4625     GstFlowReturn ret)
4626 {
4627   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4628
4629   if (stream->pad)
4630     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4631         ret);
4632   else
4633     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4634
4635   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4636   return ret;
4637 }
4638
4639 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4640  * completely clipped
4641  *
4642  * Should be used only with raw buffers */
4643 static GstBuffer *
4644 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4645     GstBuffer * buf)
4646 {
4647   guint64 start, stop, cstart, cstop, diff;
4648   GstClockTime pts, duration;
4649   gsize size, osize;
4650   gint num_rate, denom_rate;
4651   gint frame_size;
4652   gboolean clip_data;
4653   guint offset;
4654
4655   osize = size = gst_buffer_get_size (buf);
4656   offset = 0;
4657
4658   /* depending on the type, setup the clip parameters */
4659   if (stream->subtype == FOURCC_soun) {
4660     frame_size = stream->bytes_per_frame;
4661     num_rate = GST_SECOND;
4662     denom_rate = (gint) stream->rate;
4663     clip_data = TRUE;
4664   } else if (stream->subtype == FOURCC_vide) {
4665     frame_size = size;
4666     num_rate = stream->fps_n;
4667     denom_rate = stream->fps_d;
4668     clip_data = FALSE;
4669   } else
4670     goto wrong_type;
4671
4672   if (frame_size <= 0)
4673     goto bad_frame_size;
4674
4675   /* we can only clip if we have a valid pts */
4676   pts = GST_BUFFER_PTS (buf);
4677   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4678     goto no_pts;
4679
4680   duration = GST_BUFFER_DURATION (buf);
4681
4682   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4683     duration =
4684         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4685   }
4686
4687   start = pts;
4688   stop = start + duration;
4689
4690   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4691               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4692     goto clipped;
4693
4694   /* see if some clipping happened */
4695   diff = cstart - start;
4696   if (diff > 0) {
4697     pts += diff;
4698     duration -= diff;
4699
4700     if (clip_data) {
4701       /* bring clipped time to samples and to bytes */
4702       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4703       diff *= frame_size;
4704
4705       GST_DEBUG_OBJECT (qtdemux,
4706           "clipping start to %" GST_TIME_FORMAT " %"
4707           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4708
4709       offset = diff;
4710       size -= diff;
4711     }
4712   }
4713   diff = stop - cstop;
4714   if (diff > 0) {
4715     duration -= diff;
4716
4717     if (clip_data) {
4718       /* bring clipped time to samples and then to bytes */
4719       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4720       diff *= frame_size;
4721       GST_DEBUG_OBJECT (qtdemux,
4722           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4723           " bytes", GST_TIME_ARGS (cstop), diff);
4724       size -= diff;
4725     }
4726   }
4727
4728   if (offset != 0 || size != osize)
4729     gst_buffer_resize (buf, offset, size);
4730
4731   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
4732   GST_BUFFER_PTS (buf) = pts;
4733   GST_BUFFER_DURATION (buf) = duration;
4734
4735   return buf;
4736
4737   /* dropped buffer */
4738 wrong_type:
4739   {
4740     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
4741     return buf;
4742   }
4743 bad_frame_size:
4744   {
4745     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
4746     return buf;
4747   }
4748 no_pts:
4749   {
4750     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
4751     return buf;
4752   }
4753 clipped:
4754   {
4755     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
4756     gst_buffer_unref (buf);
4757     return NULL;
4758   }
4759 }
4760
4761 /* the input buffer metadata must be writable,
4762  * but time/duration etc not yet set and need not be preserved */
4763 static GstBuffer *
4764 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4765     GstBuffer * buf)
4766 {
4767   GstMapInfo map;
4768   guint nsize = 0;
4769   gchar *str;
4770
4771   /* not many cases for now */
4772   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
4773     /* send a one time dvd clut event */
4774     if (stream->pending_event && stream->pad)
4775       gst_pad_push_event (stream->pad, stream->pending_event);
4776     stream->pending_event = NULL;
4777   }
4778
4779   if (G_UNLIKELY (stream->subtype != FOURCC_text
4780           && stream->subtype != FOURCC_sbtl &&
4781           stream->subtype != FOURCC_subp)) {
4782     return buf;
4783   }
4784
4785   gst_buffer_map (buf, &map, GST_MAP_READ);
4786
4787   /* empty buffer is sent to terminate previous subtitle */
4788   if (map.size <= 2) {
4789     gst_buffer_unmap (buf, &map);
4790     gst_buffer_unref (buf);
4791     return NULL;
4792   }
4793   if (stream->subtype == FOURCC_subp) {
4794     /* That's all the processing needed for subpictures */
4795     gst_buffer_unmap (buf, &map);
4796     return buf;
4797   }
4798
4799   nsize = GST_READ_UINT16_BE (map.data);
4800   nsize = MIN (nsize, map.size - 2);
4801
4802   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
4803       nsize, map.size);
4804
4805   /* takes care of UTF-8 validation or UTF-16 recognition,
4806    * no other encoding expected */
4807   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
4808   gst_buffer_unmap (buf, &map);
4809   if (str) {
4810     gst_buffer_unref (buf);
4811     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
4812   } else {
4813     /* this should not really happen unless the subtitle is corrupted */
4814     gst_buffer_unref (buf);
4815     buf = NULL;
4816   }
4817
4818   /* FIXME ? convert optional subsequent style info to markup */
4819
4820   return buf;
4821 }
4822
4823 /* Sets a buffer's attributes properly and pushes it downstream.
4824  * Also checks for additional actions and custom processing that may
4825  * need to be done first.
4826  */
4827 static GstFlowReturn
4828 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
4829     QtDemuxStream * stream, GstBuffer * buf,
4830     GstClockTime dts, GstClockTime pts, GstClockTime duration,
4831     gboolean keyframe, GstClockTime position, guint64 byte_position)
4832 {
4833   GstFlowReturn ret = GST_FLOW_OK;
4834
4835   /* offset the timestamps according to the edit list */
4836
4837   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
4838     gchar *url;
4839     GstMapInfo map;
4840
4841     gst_buffer_map (buf, &map, GST_MAP_READ);
4842     url = g_strndup ((gchar *) map.data, map.size);
4843     gst_buffer_unmap (buf, &map);
4844     if (url != NULL && strlen (url) != 0) {
4845       /* we have RTSP redirect now */
4846       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4847           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
4848               gst_structure_new ("redirect",
4849                   "new-location", G_TYPE_STRING, url, NULL)));
4850       qtdemux->posted_redirect = TRUE;
4851     } else {
4852       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
4853           "posting");
4854     }
4855     g_free (url);
4856   }
4857
4858   /* position reporting */
4859   if (qtdemux->segment.rate >= 0) {
4860     qtdemux->segment.position = position;
4861     gst_qtdemux_sync_streams (qtdemux);
4862   }
4863
4864   if (G_UNLIKELY (!stream->pad)) {
4865     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
4866     gst_buffer_unref (buf);
4867     goto exit;
4868   }
4869
4870   /* send out pending buffers */
4871   while (stream->buffers) {
4872     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
4873
4874     if (G_UNLIKELY (stream->discont)) {
4875       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4876       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
4877       stream->discont = FALSE;
4878     } else {
4879       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4880     }
4881
4882     gst_pad_push (stream->pad, buffer);
4883
4884     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
4885   }
4886
4887   /* we're going to modify the metadata */
4888   buf = gst_buffer_make_writable (buf);
4889
4890   if (G_UNLIKELY (stream->need_process))
4891     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
4892
4893   if (!buf) {
4894     goto exit;
4895   }
4896
4897   GST_BUFFER_DTS (buf) = dts;
4898   GST_BUFFER_PTS (buf) = pts;
4899   GST_BUFFER_DURATION (buf) = duration;
4900   GST_BUFFER_OFFSET (buf) = -1;
4901   GST_BUFFER_OFFSET_END (buf) = -1;
4902
4903   if (G_UNLIKELY (stream->rgb8_palette))
4904     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
4905
4906   if (G_UNLIKELY (stream->padding)) {
4907     gst_buffer_resize (buf, stream->padding, -1);
4908   }
4909 #if 0
4910   if (G_UNLIKELY (qtdemux->element_index)) {
4911     GstClockTime stream_time;
4912
4913     stream_time =
4914         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
4915         timestamp);
4916     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
4917       GST_LOG_OBJECT (qtdemux,
4918           "adding association %" GST_TIME_FORMAT "-> %"
4919           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
4920       gst_index_add_association (qtdemux->element_index,
4921           qtdemux->index_id,
4922           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
4923           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
4924           GST_FORMAT_BYTES, byte_position, NULL);
4925     }
4926   }
4927 #endif
4928
4929   if (stream->need_clip)
4930     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
4931
4932   if (G_UNLIKELY (buf == NULL))
4933     goto exit;
4934
4935   if (G_UNLIKELY (stream->discont)) {
4936     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4937     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4938     stream->discont = FALSE;
4939   } else {
4940     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4941   }
4942
4943   if (!keyframe) {
4944     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4945     stream->on_keyframe = FALSE;
4946   } else {
4947     stream->on_keyframe = TRUE;
4948   }
4949
4950
4951   GST_LOG_OBJECT (qtdemux,
4952       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
4953       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
4954       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
4955       GST_PAD_NAME (stream->pad));
4956
4957   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
4958     GstStructure *crypto_info;
4959     QtDemuxCencSampleSetInfo *info =
4960         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4961     gint index;
4962     GstEvent *event;
4963
4964     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
4965       gst_pad_push_event (stream->pad, event);
4966     }
4967
4968     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
4969     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
4970       /* steal structure from array */
4971       crypto_info = g_ptr_array_index (info->crypto_info, index);
4972       g_ptr_array_index (info->crypto_info, index) = NULL;
4973       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
4974       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
4975         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
4976     }
4977   }
4978
4979   ret = gst_pad_push (stream->pad, buf);
4980
4981   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
4982     /* mark position in stream, we'll need this to know when to send GAP event */
4983     stream->segment.position = pts + duration;
4984   }
4985
4986 exit:
4987   return ret;
4988 }
4989
4990 static const QtDemuxRandomAccessEntry *
4991 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4992     GstClockTime pos, gboolean after)
4993 {
4994   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
4995   guint n_entries = stream->n_ra_entries;
4996   guint i;
4997
4998   /* we assume the table is sorted */
4999   for (i = 0; i < n_entries; ++i) {
5000     if (entries[i].ts > pos)
5001       break;
5002   }
5003
5004   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5005    * probably okay to assume that the index lists the very first fragment */
5006   if (i == 0)
5007     return &entries[0];
5008
5009   if (after)
5010     return &entries[i];
5011   else
5012     return &entries[i - 1];
5013 }
5014
5015 static gboolean
5016 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5017 {
5018   const QtDemuxRandomAccessEntry *best_entry = NULL;
5019   guint i;
5020
5021   GST_OBJECT_LOCK (qtdemux);
5022
5023   g_assert (qtdemux->n_streams > 0);
5024
5025   for (i = 0; i < qtdemux->n_streams; i++) {
5026     const QtDemuxRandomAccessEntry *entry;
5027     QtDemuxStream *stream;
5028     gboolean is_audio_or_video;
5029
5030     stream = qtdemux->streams[i];
5031
5032     g_free (stream->samples);
5033     stream->samples = NULL;
5034     stream->n_samples = 0;
5035     stream->stbl_index = -1;    /* no samples have yet been parsed */
5036     stream->sample_index = -1;
5037
5038     if (stream->ra_entries == NULL)
5039       continue;
5040
5041     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5042       is_audio_or_video = TRUE;
5043     else
5044       is_audio_or_video = FALSE;
5045
5046     entry =
5047         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5048         stream->time_position, !is_audio_or_video);
5049
5050     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5051         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5052
5053     stream->pending_seek = entry;
5054
5055     /* decide position to jump to just based on audio/video tracks, not subs */
5056     if (!is_audio_or_video)
5057       continue;
5058
5059     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5060       best_entry = entry;
5061   }
5062
5063   if (best_entry == NULL) {
5064     GST_OBJECT_UNLOCK (qtdemux);
5065     return FALSE;
5066   }
5067
5068   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5069       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5070       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5071       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5072
5073   qtdemux->moof_offset = best_entry->moof_offset;
5074
5075   qtdemux_add_fragmented_samples (qtdemux);
5076
5077   GST_OBJECT_UNLOCK (qtdemux);
5078   return TRUE;
5079 }
5080
5081 static GstFlowReturn
5082 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5083 {
5084   GstFlowReturn ret = GST_FLOW_OK;
5085   GstBuffer *buf = NULL;
5086   QtDemuxStream *stream;
5087   GstClockTime min_time;
5088   guint64 offset = 0;
5089   GstClockTime dts = GST_CLOCK_TIME_NONE;
5090   GstClockTime pts = GST_CLOCK_TIME_NONE;
5091   GstClockTime duration = 0;
5092   gboolean keyframe = FALSE;
5093   guint sample_size = 0;
5094   gboolean empty = 0;
5095   guint size;
5096   gint index;
5097   gint i;
5098
5099   gst_qtdemux_push_pending_newsegment (qtdemux);
5100
5101   if (qtdemux->fragmented_seek_pending) {
5102     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5103     gst_qtdemux_do_fragmented_seek (qtdemux);
5104     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5105     qtdemux->fragmented_seek_pending = FALSE;
5106   }
5107
5108   /* Figure out the next stream sample to output, min_time is expressed in
5109    * global time and runs over the edit list segments. */
5110   min_time = G_MAXUINT64;
5111   index = -1;
5112   for (i = 0; i < qtdemux->n_streams; i++) {
5113     GstClockTime position;
5114
5115     stream = qtdemux->streams[i];
5116     position = stream->time_position;
5117
5118     /* position of -1 is EOS */
5119     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5120       min_time = position;
5121       index = i;
5122     }
5123   }
5124   /* all are EOS */
5125   if (G_UNLIKELY (index == -1)) {
5126     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5127     goto eos;
5128   }
5129
5130   /* check for segment end */
5131   if (G_UNLIKELY (qtdemux->segment.stop != -1
5132           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5133               || (qtdemux->segment.rate < 0
5134                   && qtdemux->segment.start > min_time))
5135           && qtdemux->streams[index]->on_keyframe)) {
5136     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5137     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5138     goto eos_stream;
5139   }
5140
5141   /* gap events for subtitle streams */
5142   for (i = 0; i < qtdemux->n_streams; i++) {
5143     stream = qtdemux->streams[i];
5144     if (stream->pad && (stream->subtype == FOURCC_subp
5145             || stream->subtype == FOURCC_text
5146             || stream->subtype == FOURCC_sbtl)) {
5147       /* send one second gap events until the stream catches up */
5148       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5149       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5150           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5151           stream->segment.position + GST_SECOND < min_time) {
5152         GstEvent *gap =
5153             gst_event_new_gap (stream->segment.position, GST_SECOND);
5154         gst_pad_push_event (stream->pad, gap);
5155         stream->segment.position += GST_SECOND;
5156       }
5157     }
5158   }
5159
5160   stream = qtdemux->streams[index];
5161   if (stream->new_caps) {
5162     gst_qtdemux_configure_stream (qtdemux, stream);
5163     qtdemux_do_allocation (qtdemux, stream);
5164   }
5165
5166   /* fetch info for the current sample of this stream */
5167   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5168               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5169     goto eos_stream;
5170
5171   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5172   if (G_UNLIKELY (qtdemux->
5173           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5174     if (stream->subtype == FOURCC_vide && !keyframe) {
5175       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5176       goto next;
5177     }
5178   }
5179
5180   GST_DEBUG_OBJECT (qtdemux,
5181       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5182       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5183       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5184       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5185
5186   if (G_UNLIKELY (empty)) {
5187     /* empty segment, push a gap and move to the next one */
5188     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5189     stream->segment.position = pts + duration;
5190     goto next;
5191   }
5192
5193   /* hmm, empty sample, skip and move to next sample */
5194   if (G_UNLIKELY (sample_size <= 0))
5195     goto next;
5196
5197   /* last pushed sample was out of boundary, goto next sample */
5198   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5199     goto next;
5200
5201   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5202     size = sample_size;
5203   } else {
5204     GST_DEBUG_OBJECT (qtdemux,
5205         "size %d larger than stream max_buffer_size %d, trimming",
5206         sample_size, stream->max_buffer_size);
5207     size =
5208         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5209   }
5210
5211   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5212       offset);
5213
5214   if (stream->use_allocator) {
5215     /* if we have a per-stream allocator, use it */
5216     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5217   }
5218
5219   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5220       size, &buf);
5221   if (G_UNLIKELY (ret != GST_FLOW_OK))
5222     goto beach;
5223
5224   if (size != sample_size) {
5225     pts += gst_util_uint64_scale_int (GST_SECOND,
5226         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5227     dts += gst_util_uint64_scale_int (GST_SECOND,
5228         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5229     duration = gst_util_uint64_scale_int (GST_SECOND,
5230         size / stream->bytes_per_frame, stream->timescale);
5231   }
5232
5233   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5234       dts, pts, duration, keyframe, min_time, offset);
5235
5236   if (size != sample_size) {
5237     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5238     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5239
5240     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5241         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5242     if (time_position >= segment->media_start) {
5243       /* inside the segment, update time_position, looks very familiar to
5244        * GStreamer segments, doesn't it? */
5245       stream->time_position = (time_position - segment->media_start) +
5246           segment->time;
5247     } else {
5248       /* not yet in segment, time does not yet increment. This means
5249        * that we are still prerolling keyframes to the decoder so it can
5250        * decode the first sample of the segment. */
5251       stream->time_position = segment->time;
5252     }
5253   }
5254
5255   /* combine flows */
5256   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5257   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5258    * we have no more data for the pad to push */
5259   if (ret == GST_FLOW_EOS)
5260     ret = GST_FLOW_OK;
5261
5262   stream->offset_in_sample += size;
5263   if (stream->offset_in_sample >= sample_size) {
5264     gst_qtdemux_advance_sample (qtdemux, stream);
5265   }
5266   goto beach;
5267
5268 next:
5269   gst_qtdemux_advance_sample (qtdemux, stream);
5270
5271 beach:
5272   return ret;
5273
5274   /* special cases */
5275 eos:
5276   {
5277     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5278     ret = GST_FLOW_EOS;
5279     goto beach;
5280   }
5281 eos_stream:
5282   {
5283     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5284     /* EOS will be raised if all are EOS */
5285     ret = GST_FLOW_OK;
5286     goto beach;
5287   }
5288 }
5289
5290 static void
5291 gst_qtdemux_loop (GstPad * pad)
5292 {
5293   GstQTDemux *qtdemux;
5294   guint64 cur_offset;
5295   GstFlowReturn ret;
5296
5297   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5298
5299   cur_offset = qtdemux->offset;
5300   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5301       cur_offset, qtdemux->state);
5302
5303   switch (qtdemux->state) {
5304     case QTDEMUX_STATE_INITIAL:
5305     case QTDEMUX_STATE_HEADER:
5306       ret = gst_qtdemux_loop_state_header (qtdemux);
5307       break;
5308     case QTDEMUX_STATE_MOVIE:
5309       ret = gst_qtdemux_loop_state_movie (qtdemux);
5310       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5311         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5312       }
5313       break;
5314     default:
5315       /* ouch */
5316       goto invalid_state;
5317   }
5318
5319   /* if something went wrong, pause */
5320   if (ret != GST_FLOW_OK)
5321     goto pause;
5322
5323 done:
5324   gst_object_unref (qtdemux);
5325   return;
5326
5327   /* ERRORS */
5328 invalid_state:
5329   {
5330     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5331         (NULL), ("streaming stopped, invalid state"));
5332     gst_pad_pause_task (pad);
5333     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5334     goto done;
5335   }
5336 pause:
5337   {
5338     const gchar *reason = gst_flow_get_name (ret);
5339
5340     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5341
5342     gst_pad_pause_task (pad);
5343
5344     /* fatal errors need special actions */
5345     /* check EOS */
5346     if (ret == GST_FLOW_EOS) {
5347       if (qtdemux->n_streams == 0) {
5348         /* we have no streams, post an error */
5349         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5350       }
5351       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5352         gint64 stop;
5353
5354         if ((stop = qtdemux->segment.stop) == -1)
5355           stop = qtdemux->segment.duration;
5356
5357         if (qtdemux->segment.rate >= 0) {
5358           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5359           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5360               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5361                   GST_FORMAT_TIME, stop));
5362           gst_qtdemux_push_event (qtdemux,
5363               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
5364         } else {
5365           /*  For Reverse Playback */
5366           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5367           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5368               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5369                   GST_FORMAT_TIME, qtdemux->segment.start));
5370           gst_qtdemux_push_event (qtdemux,
5371               gst_event_new_segment_done (GST_FORMAT_TIME,
5372                   qtdemux->segment.start));
5373         }
5374       } else {
5375         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5376         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5377       }
5378     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5379       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5380           (NULL), ("streaming stopped, reason %s", reason));
5381       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5382     }
5383     goto done;
5384   }
5385 }
5386
5387 /*
5388  * has_next_entry
5389  *
5390  * Returns if there are samples to be played.
5391  */
5392 static gboolean
5393 has_next_entry (GstQTDemux * demux)
5394 {
5395   QtDemuxStream *stream;
5396   int i;
5397
5398   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5399
5400   for (i = 0; i < demux->n_streams; i++) {
5401     stream = demux->streams[i];
5402
5403     if (stream->sample_index == -1) {
5404       stream->sample_index = 0;
5405       stream->offset_in_sample = 0;
5406     }
5407
5408     if (stream->sample_index >= stream->n_samples) {
5409       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5410       continue;
5411     }
5412     GST_DEBUG_OBJECT (demux, "Found a sample");
5413     return TRUE;
5414   }
5415
5416   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5417   return FALSE;
5418 }
5419
5420 /*
5421  * next_entry_size
5422  *
5423  * Returns the size of the first entry at the current offset.
5424  * If -1, there are none (which means EOS or empty file).
5425  */
5426 static guint64
5427 next_entry_size (GstQTDemux * demux)
5428 {
5429   QtDemuxStream *stream;
5430   int i;
5431   int smallidx = -1;
5432   guint64 smalloffs = (guint64) - 1;
5433   QtDemuxSample *sample;
5434
5435   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5436       demux->offset);
5437
5438   for (i = 0; i < demux->n_streams; i++) {
5439     stream = demux->streams[i];
5440
5441     if (stream->sample_index == -1) {
5442       stream->sample_index = 0;
5443       stream->offset_in_sample = 0;
5444     }
5445
5446     if (stream->sample_index >= stream->n_samples) {
5447       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5448       continue;
5449     }
5450
5451     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5452       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5453           stream->sample_index);
5454       return -1;
5455     }
5456
5457     sample = &stream->samples[stream->sample_index];
5458
5459     GST_LOG_OBJECT (demux,
5460         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5461         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5462         sample->offset, sample->size);
5463
5464     if (((smalloffs == -1)
5465             || (sample->offset < smalloffs)) && (sample->size)) {
5466       smallidx = i;
5467       smalloffs = sample->offset;
5468     }
5469   }
5470
5471   GST_LOG_OBJECT (demux,
5472       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5473       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5474
5475   if (smallidx == -1)
5476     return -1;
5477
5478   stream = demux->streams[smallidx];
5479   sample = &stream->samples[stream->sample_index];
5480
5481   if (sample->offset >= demux->offset) {
5482     demux->todrop = sample->offset - demux->offset;
5483     return sample->size + demux->todrop;
5484   }
5485
5486   GST_DEBUG_OBJECT (demux,
5487       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5488   return -1;
5489 }
5490
5491 static void
5492 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5493 {
5494   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5495
5496   gst_element_post_message (GST_ELEMENT_CAST (demux),
5497       gst_message_new_element (GST_OBJECT_CAST (demux),
5498           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5499 }
5500
5501 static gboolean
5502 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5503 {
5504   GstEvent *event;
5505   gboolean res = 0;
5506
5507   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5508
5509   event =
5510       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5511       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5512       GST_SEEK_TYPE_NONE, -1);
5513
5514   /* store seqnum to drop flush events, they don't need to reach downstream */
5515   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
5516   res = gst_pad_push_event (demux->sinkpad, event);
5517   demux->offset_seek_seqnum = 0;
5518
5519   return res;
5520 }
5521
5522 /* check for seekable upstream, above and beyond a mere query */
5523 static void
5524 gst_qtdemux_check_seekability (GstQTDemux * demux)
5525 {
5526   GstQuery *query;
5527   gboolean seekable = FALSE;
5528   gint64 start = -1, stop = -1;
5529
5530   if (demux->upstream_size)
5531     return;
5532
5533   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5534   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5535     GST_DEBUG_OBJECT (demux, "seeking query failed");
5536     goto done;
5537   }
5538
5539   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5540
5541   /* try harder to query upstream size if we didn't get it the first time */
5542   if (seekable && stop == -1) {
5543     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5544     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5545   }
5546
5547   /* if upstream doesn't know the size, it's likely that it's not seekable in
5548    * practice even if it technically may be seekable */
5549   if (seekable && (start != 0 || stop <= start)) {
5550     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5551     seekable = FALSE;
5552   }
5553
5554 done:
5555   gst_query_unref (query);
5556
5557   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5558       G_GUINT64_FORMAT ")", seekable, start, stop);
5559   demux->upstream_seekable = seekable;
5560   demux->upstream_size = seekable ? stop : -1;
5561 }
5562
5563 static void
5564 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5565 {
5566   g_return_if_fail (bytes <= demux->todrop);
5567
5568   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5569   gst_adapter_flush (demux->adapter, bytes);
5570   demux->neededbytes -= bytes;
5571   demux->offset += bytes;
5572   demux->todrop -= bytes;
5573 }
5574
5575 static void
5576 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
5577 {
5578   if (G_UNLIKELY (demux->pending_newsegment)) {
5579     gint i;
5580
5581     gst_qtdemux_push_pending_newsegment (demux);
5582     /* clear to send tags on all streams */
5583     for (i = 0; i < demux->n_streams; i++) {
5584       QtDemuxStream *stream;
5585       stream = demux->streams[i];
5586       gst_qtdemux_push_tags (demux, stream);
5587       if (stream->sparse) {
5588         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5589         gst_pad_push_event (stream->pad,
5590             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
5591       }
5592     }
5593   }
5594 }
5595
5596 static void
5597 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
5598     QtDemuxStream * stream)
5599 {
5600   gint i;
5601
5602   /* Push any initial gap segments before proceeding to the
5603    * 'real' data */
5604   for (i = 0; i < stream->n_segments; i++) {
5605     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
5606
5607     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
5608       GstClockTime ts, dur;
5609       GstEvent *gap;
5610
5611       ts = stream->time_position;
5612       dur =
5613           stream->segments[i].duration - (stream->time_position -
5614           stream->segments[i].time);
5615       gap = gst_event_new_gap (ts, dur);
5616       stream->time_position += dur;
5617
5618       GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
5619           "segment: %" GST_PTR_FORMAT, gap);
5620       gst_pad_push_event (stream->pad, gap);
5621     } else {
5622       /* Only support empty segment at the beginning followed by
5623        * one non-empty segment, this was checked when parsing the
5624        * edts atom, arriving here is unexpected */
5625       g_assert (i + 1 == stream->n_segments);
5626       break;
5627     }
5628   }
5629 }
5630
5631 static GstFlowReturn
5632 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5633 {
5634   GstQTDemux *demux;
5635
5636   demux = GST_QTDEMUX (parent);
5637
5638   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5639     gint i;
5640
5641     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5642
5643     for (i = 0; i < demux->n_streams; i++) {
5644       demux->streams[i]->discont = TRUE;
5645     }
5646
5647     /* Reverse fragmented playback, need to flush all we have before
5648      * consuming a new fragment.
5649      * The samples array have the timestamps calculated by accumulating the
5650      * durations but this won't work for reverse playback of fragments as
5651      * the timestamps of a subsequent fragment should be smaller than the
5652      * previously received one. */
5653     if (demux->fragmented && demux->segment.rate < 0) {
5654       gst_qtdemux_process_adapter (demux, TRUE);
5655       for (i = 0; i < demux->n_streams; i++)
5656         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5657     }
5658   }
5659
5660   gst_adapter_push (demux->adapter, inbuf);
5661
5662   GST_DEBUG_OBJECT (demux,
5663       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5664       demux->neededbytes, gst_adapter_available (demux->adapter));
5665
5666   return gst_qtdemux_process_adapter (demux, FALSE);
5667 }
5668
5669 static GstFlowReturn
5670 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5671 {
5672   GstFlowReturn ret = GST_FLOW_OK;
5673
5674   /* we never really mean to buffer that much */
5675   if (demux->neededbytes == -1) {
5676     goto eos;
5677   }
5678
5679   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
5680       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
5681
5682     GST_DEBUG_OBJECT (demux,
5683         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
5684         demux->state, demux->neededbytes, demux->offset);
5685
5686     switch (demux->state) {
5687       case QTDEMUX_STATE_INITIAL:{
5688         const guint8 *data;
5689         guint32 fourcc;
5690         guint64 size;
5691
5692         gst_qtdemux_check_seekability (demux);
5693
5694         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5695
5696         /* get fourcc/length, set neededbytes */
5697         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
5698             &size, &fourcc);
5699         gst_adapter_unmap (demux->adapter);
5700         data = NULL;
5701         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
5702             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
5703         if (size == 0) {
5704           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5705               (_("This file is invalid and cannot be played.")),
5706               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
5707                   GST_FOURCC_ARGS (fourcc)));
5708           ret = GST_FLOW_ERROR;
5709           break;
5710         }
5711         if (fourcc == FOURCC_mdat) {
5712           gint next_entry = next_entry_size (demux);
5713           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
5714             /* we have the headers, start playback */
5715             demux->state = QTDEMUX_STATE_MOVIE;
5716             demux->neededbytes = next_entry;
5717             demux->mdatleft = size;
5718           } else {
5719             /* no headers yet, try to get them */
5720             guint bs;
5721             gboolean res;
5722             guint64 old, target;
5723
5724           buffer_data:
5725             old = demux->offset;
5726             target = old + size;
5727
5728             /* try to jump over the atom with a seek */
5729             /* only bother if it seems worth doing so,
5730              * and avoids possible upstream/server problems */
5731             if (demux->upstream_seekable &&
5732                 demux->upstream_size > 4 * (1 << 20)) {
5733               res = qtdemux_seek_offset (demux, target);
5734             } else {
5735               GST_DEBUG_OBJECT (demux, "skipping seek");
5736               res = FALSE;
5737             }
5738
5739             if (res) {
5740               GST_DEBUG_OBJECT (demux, "seek success");
5741               /* remember the offset fo the first mdat so we can seek back to it
5742                * after we have the headers */
5743               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
5744                 demux->first_mdat = old;
5745                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
5746                     demux->first_mdat);
5747               }
5748               /* seek worked, continue reading */
5749               demux->offset = target;
5750               demux->neededbytes = 16;
5751               demux->state = QTDEMUX_STATE_INITIAL;
5752             } else {
5753               /* seek failed, need to buffer */
5754               demux->offset = old;
5755               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
5756               /* there may be multiple mdat (or alike) buffers */
5757               /* sanity check */
5758               if (demux->mdatbuffer)
5759                 bs = gst_buffer_get_size (demux->mdatbuffer);
5760               else
5761                 bs = 0;
5762               if (size + bs > 10 * (1 << 20))
5763                 goto no_moov;
5764               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
5765               demux->neededbytes = size;
5766               if (!demux->mdatbuffer)
5767                 demux->mdatoffset = demux->offset;
5768             }
5769           }
5770         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
5771           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5772               (_("This file is invalid and cannot be played.")),
5773               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
5774                   GST_FOURCC_ARGS (fourcc), size));
5775           ret = GST_FLOW_ERROR;
5776           break;
5777         } else {
5778           /* this means we already started buffering and still no moov header,
5779            * let's continue buffering everything till we get moov */
5780           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
5781                   || fourcc == FOURCC_moof))
5782             goto buffer_data;
5783           demux->neededbytes = size;
5784           demux->state = QTDEMUX_STATE_HEADER;
5785         }
5786         break;
5787       }
5788       case QTDEMUX_STATE_HEADER:{
5789         const guint8 *data;
5790         guint32 fourcc;
5791
5792         GST_DEBUG_OBJECT (demux, "In header");
5793
5794         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5795
5796         /* parse the header */
5797         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
5798             &fourcc);
5799         if (fourcc == FOURCC_moov) {
5800           gint n;
5801           gboolean got_samples = FALSE;
5802
5803           /* in usual fragmented setup we could try to scan for more
5804            * and end up at the the moov (after mdat) again */
5805           if (demux->got_moov && demux->n_streams > 0 &&
5806               (!demux->fragmented
5807                   || demux->last_moov_offset == demux->offset)) {
5808             GST_DEBUG_OBJECT (demux,
5809                 "Skipping moov atom as we have (this) one already");
5810           } else {
5811             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
5812
5813             if (demux->got_moov && demux->fragmented) {
5814               GST_DEBUG_OBJECT (demux,
5815                   "Got a second moov, clean up data from old one");
5816               if (demux->moov_node)
5817                 g_node_destroy (demux->moov_node);
5818               demux->moov_node = NULL;
5819               demux->moov_node_compressed = NULL;
5820             } else {
5821               /* prepare newsegment to send when streaming actually starts */
5822               if (!demux->pending_newsegment)
5823                 demux->pending_newsegment =
5824                     gst_event_new_segment (&demux->segment);
5825             }
5826
5827             demux->last_moov_offset = demux->offset;
5828
5829             qtdemux_parse_moov (demux, data, demux->neededbytes);
5830             qtdemux_node_dump (demux, demux->moov_node);
5831             qtdemux_parse_tree (demux);
5832             qtdemux_prepare_streams (demux);
5833
5834             for (n = 0; n < demux->n_streams; n++) {
5835               QtDemuxStream *stream = demux->streams[n];
5836               got_samples |= stream->stbl_index >= 0;
5837             }
5838             if (!demux->fragmented || got_samples) {
5839               if (!demux->got_moov) {
5840                 qtdemux_expose_streams (demux);
5841               } else {
5842                 for (n = 0; n < demux->n_streams; n++) {
5843                   QtDemuxStream *stream = demux->streams[n];
5844                   gst_qtdemux_configure_stream (demux, stream);
5845                 }
5846               }
5847               gst_qtdemux_check_send_pending_segment (demux);
5848               demux->pending_configure = FALSE;
5849             } else {
5850               demux->pending_configure = TRUE;
5851             }
5852
5853             demux->got_moov = TRUE;
5854
5855             /* fragmented streams headers shouldn't contain edts atoms */
5856             if (!demux->fragmented) {
5857               for (n = 0; n < demux->n_streams; n++) {
5858                 gst_qtdemux_stream_send_initial_gap_segments (demux,
5859                     demux->streams[n]);
5860               }
5861             }
5862
5863             g_node_destroy (demux->moov_node);
5864             demux->moov_node = NULL;
5865             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
5866           }
5867         } else if (fourcc == FOURCC_moof) {
5868           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
5869             guint64 dist = 0;
5870             GstClockTime prev_pts;
5871             guint64 prev_offset;
5872             gint n;
5873
5874             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
5875
5876             /*
5877              * The timestamp of the moof buffer is relevant as some scenarios
5878              * won't have the initial timestamp in the atoms. Whenever a new
5879              * buffer has started, we get that buffer's PTS and use it as a base
5880              * timestamp for the trun entries.
5881              *
5882              * To keep track of the current buffer timestamp and starting point
5883              * we use gst_adapter_prev_pts that gives us the PTS and the distance
5884              * from the beggining of the buffer, with the distance and demux->offset
5885              * we know if it is still the same buffer or not.
5886              */
5887             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
5888             prev_offset = demux->offset - dist;
5889             if (demux->fragment_start_offset == -1
5890                 || prev_offset > demux->fragment_start_offset) {
5891               demux->fragment_start_offset = prev_offset;
5892               demux->fragment_start = prev_pts;
5893               GST_DEBUG_OBJECT (demux,
5894                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
5895                   GST_TIME_FORMAT, demux->fragment_start_offset,
5896                   GST_TIME_ARGS (demux->fragment_start));
5897             }
5898
5899             demux->moof_offset = demux->offset;
5900             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
5901                     demux->offset, NULL)) {
5902               gst_adapter_unmap (demux->adapter);
5903               ret = GST_FLOW_ERROR;
5904               goto done;
5905             }
5906             /* in MSS we need to expose the pads after the first moof as we won't get a moov 
5907              * Also, fragmented format need to be exposed if a moov have no valid sample data */
5908             if (demux->mss_mode || demux->pending_configure) {
5909               if (!demux->exposed) {
5910                 if (!demux->pending_newsegment) {
5911                   GstSegment segment;
5912                   gst_segment_init (&segment, GST_FORMAT_TIME);
5913                   GST_DEBUG_OBJECT (demux, "new pending_newsegment");
5914                   demux->pending_newsegment = gst_event_new_segment (&segment);
5915                 }
5916                 qtdemux_expose_streams (demux);
5917               } else {
5918                 for (n = 0; n < demux->n_streams; n++) {
5919                   QtDemuxStream *stream = demux->streams[n];
5920                   gst_qtdemux_configure_stream (demux, stream);
5921                 }
5922               }
5923               gst_qtdemux_check_send_pending_segment (demux);
5924               demux->pending_configure = FALSE;
5925             }
5926           } else {
5927             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
5928           }
5929         } else if (fourcc == FOURCC_ftyp) {
5930           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
5931           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
5932         } else if (fourcc == FOURCC_uuid) {
5933           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
5934           qtdemux_parse_uuid (demux, data, demux->neededbytes);
5935         } else if (fourcc == FOURCC_sidx) {
5936           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
5937           qtdemux_parse_sidx (demux, data, demux->neededbytes);
5938         } else {
5939           GST_WARNING_OBJECT (demux,
5940               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
5941               GST_FOURCC_ARGS (fourcc));
5942           /* Let's jump that one and go back to initial state */
5943         }
5944         gst_adapter_unmap (demux->adapter);
5945         data = NULL;
5946
5947         if (demux->mdatbuffer && demux->n_streams) {
5948           gsize remaining_data_size = 0;
5949
5950           /* the mdat was before the header */
5951           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
5952               demux->n_streams, demux->mdatbuffer);
5953           /* restore our adapter/offset view of things with upstream;
5954            * put preceding buffered data ahead of current moov data.
5955            * This should also handle evil mdat, moov, mdat cases and alike */
5956           gst_adapter_flush (demux->adapter, demux->neededbytes);
5957
5958           /* Store any remaining data after the mdat for later usage */
5959           remaining_data_size = gst_adapter_available (demux->adapter);
5960           if (remaining_data_size > 0) {
5961             g_assert (demux->restoredata_buffer == NULL);
5962             demux->restoredata_buffer =
5963                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
5964             demux->restoredata_offset = demux->offset + demux->neededbytes;
5965             GST_DEBUG_OBJECT (demux,
5966                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
5967                 G_GUINT64_FORMAT, remaining_data_size,
5968                 demux->restoredata_offset);
5969           }
5970
5971           gst_adapter_push (demux->adapter, demux->mdatbuffer);
5972           demux->mdatbuffer = NULL;
5973           demux->offset = demux->mdatoffset;
5974           demux->neededbytes = next_entry_size (demux);
5975           demux->state = QTDEMUX_STATE_MOVIE;
5976           demux->mdatleft = gst_adapter_available (demux->adapter);
5977         } else {
5978           GST_DEBUG_OBJECT (demux, "Carrying on normally");
5979           gst_adapter_flush (demux->adapter, demux->neededbytes);
5980
5981           /* only go back to the mdat if there are samples to play */
5982           if (demux->got_moov && demux->first_mdat != -1
5983               && has_next_entry (demux)) {
5984             gboolean res;
5985
5986             /* we need to seek back */
5987             res = qtdemux_seek_offset (demux, demux->first_mdat);
5988             if (res) {
5989               demux->offset = demux->first_mdat;
5990             } else {
5991               GST_DEBUG_OBJECT (demux, "Seek back failed");
5992             }
5993           } else {
5994             demux->offset += demux->neededbytes;
5995           }
5996           demux->neededbytes = 16;
5997           demux->state = QTDEMUX_STATE_INITIAL;
5998         }
5999
6000         break;
6001       }
6002       case QTDEMUX_STATE_BUFFER_MDAT:{
6003         GstBuffer *buf;
6004         guint8 fourcc[4];
6005
6006         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6007             demux->offset);
6008         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6009         gst_buffer_extract (buf, 0, fourcc, 4);
6010         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6011             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6012         if (demux->mdatbuffer)
6013           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6014         else
6015           demux->mdatbuffer = buf;
6016         demux->offset += demux->neededbytes;
6017         demux->neededbytes = 16;
6018         demux->state = QTDEMUX_STATE_INITIAL;
6019         gst_qtdemux_post_progress (demux, 1, 1);
6020
6021         break;
6022       }
6023       case QTDEMUX_STATE_MOVIE:{
6024         QtDemuxStream *stream = NULL;
6025         QtDemuxSample *sample;
6026         int i = -1;
6027         GstClockTime dts, pts, duration;
6028         gboolean keyframe;
6029
6030         GST_DEBUG_OBJECT (demux,
6031             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6032
6033         if (demux->fragmented) {
6034           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6035               demux->mdatleft);
6036           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6037             /* if needed data starts within this atom,
6038              * then it should not exceed this atom */
6039             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6040               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6041                   (_("This file is invalid and cannot be played.")),
6042                   ("sample data crosses atom boundary"));
6043               ret = GST_FLOW_ERROR;
6044               break;
6045             }
6046             demux->mdatleft -= demux->neededbytes;
6047           } else {
6048             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6049             /* so we are dropping more than left in this atom */
6050             gst_qtdemux_drop_data (demux, demux->mdatleft);
6051             demux->mdatleft = 0;
6052
6053             /* need to resume atom parsing so we do not miss any other pieces */
6054             demux->state = QTDEMUX_STATE_INITIAL;
6055             demux->neededbytes = 16;
6056
6057             /* check if there was any stored post mdat data from previous buffers */
6058             if (demux->restoredata_buffer) {
6059               g_assert (gst_adapter_available (demux->adapter) == 0);
6060
6061               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6062               demux->restoredata_buffer = NULL;
6063               demux->offset = demux->restoredata_offset;
6064             }
6065
6066             break;
6067           }
6068         }
6069
6070         if (demux->todrop) {
6071           if (demux->cenc_aux_info_offset > 0) {
6072             GstByteReader br;
6073             const guint8 *data;
6074
6075             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6076             data = gst_adapter_map (demux->adapter, demux->todrop);
6077             gst_byte_reader_init (&br, data + 8, demux->todrop);
6078             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6079                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6080               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6081               ret = GST_FLOW_ERROR;
6082               gst_adapter_unmap (demux->adapter);
6083               g_free (demux->cenc_aux_info_sizes);
6084               demux->cenc_aux_info_sizes = NULL;
6085               goto done;
6086             }
6087             demux->cenc_aux_info_offset = 0;
6088             g_free (demux->cenc_aux_info_sizes);
6089             demux->cenc_aux_info_sizes = NULL;
6090             gst_adapter_unmap (demux->adapter);
6091           }
6092           gst_qtdemux_drop_data (demux, demux->todrop);
6093         }
6094
6095         /* first buffer? */
6096         /* initial newsegment sent here after having added pads,
6097          * possible others in sink_event */
6098         gst_qtdemux_check_send_pending_segment (demux);
6099
6100         /* Figure out which stream this packet belongs to */
6101         for (i = 0; i < demux->n_streams; i++) {
6102           stream = demux->streams[i];
6103           if (stream->sample_index >= stream->n_samples)
6104             continue;
6105           GST_LOG_OBJECT (demux,
6106               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6107               " / size:%d)", i, stream->sample_index,
6108               stream->samples[stream->sample_index].offset,
6109               stream->samples[stream->sample_index].size);
6110
6111           if (stream->samples[stream->sample_index].offset == demux->offset)
6112             break;
6113         }
6114
6115         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6116           goto unknown_stream;
6117
6118         if (stream->new_caps) {
6119           gst_qtdemux_configure_stream (demux, stream);
6120         }
6121
6122         /* Put data in a buffer, set timestamps, caps, ... */
6123         sample = &stream->samples[stream->sample_index];
6124
6125         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6126           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6127               GST_FOURCC_ARGS (stream->fourcc));
6128
6129           dts = QTSAMPLE_DTS (stream, sample);
6130           pts = QTSAMPLE_PTS (stream, sample);
6131           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6132           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6133
6134           /* check for segment end */
6135           if (G_UNLIKELY (demux->segment.stop != -1
6136                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6137             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6138             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6139
6140             /* skip this data, stream is EOS */
6141             gst_adapter_flush (demux->adapter, demux->neededbytes);
6142
6143             /* check if all streams are eos */
6144             ret = GST_FLOW_EOS;
6145             for (i = 0; i < demux->n_streams; i++) {
6146               if (!STREAM_IS_EOS (demux->streams[i])) {
6147                 ret = GST_FLOW_OK;
6148                 break;
6149               }
6150             }
6151
6152             if (ret == GST_FLOW_EOS) {
6153               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6154               goto eos;
6155             }
6156           } else {
6157             GstBuffer *outbuf;
6158
6159             outbuf =
6160                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6161
6162             /* FIXME: should either be an assert or a plain check */
6163             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6164
6165             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6166                 dts, pts, duration, keyframe, dts, demux->offset);
6167           }
6168
6169           /* combine flows */
6170           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6171           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6172             goto non_ok_unlinked_flow;
6173         } else {
6174           /* skip this data, stream is EOS */
6175           gst_adapter_flush (demux->adapter, demux->neededbytes);
6176         }
6177
6178         stream->sample_index++;
6179         stream->offset_in_sample = 0;
6180
6181         /* update current offset and figure out size of next buffer */
6182         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6183             demux->offset, demux->neededbytes);
6184         demux->offset += demux->neededbytes;
6185         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6186             demux->offset);
6187
6188         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6189           if (demux->fragmented) {
6190             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6191             /* there may be more to follow, only finish this atom */
6192             demux->todrop = demux->mdatleft;
6193             demux->neededbytes = demux->todrop;
6194             break;
6195           }
6196           goto eos;
6197         }
6198         break;
6199       }
6200       default:
6201         goto invalid_state;
6202     }
6203   }
6204
6205   /* when buffering movie data, at least show user something is happening */
6206   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6207       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6208     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6209         demux->neededbytes);
6210   }
6211 done:
6212
6213   return ret;
6214
6215   /* ERRORS */
6216 non_ok_unlinked_flow:
6217   {
6218     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6219         gst_flow_get_name (ret));
6220     return ret;
6221   }
6222 unknown_stream:
6223   {
6224     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6225     ret = GST_FLOW_ERROR;
6226     goto done;
6227   }
6228 eos:
6229   {
6230     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6231     ret = GST_FLOW_EOS;
6232     goto done;
6233   }
6234 invalid_state:
6235   {
6236     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6237         (NULL), ("qtdemuxer invalid state %d", demux->state));
6238     ret = GST_FLOW_ERROR;
6239     goto done;
6240   }
6241 no_moov:
6242   {
6243     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6244         (NULL), ("no 'moov' atom within the first 10 MB"));
6245     ret = GST_FLOW_ERROR;
6246     goto done;
6247   }
6248 }
6249
6250 static gboolean
6251 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6252 {
6253   GstQuery *query;
6254   gboolean pull_mode;
6255
6256   query = gst_query_new_scheduling ();
6257
6258   if (!gst_pad_peer_query (sinkpad, query)) {
6259     gst_query_unref (query);
6260     goto activate_push;
6261   }
6262
6263   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6264       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6265   gst_query_unref (query);
6266
6267   if (!pull_mode)
6268     goto activate_push;
6269
6270   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6271   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6272
6273 activate_push:
6274   {
6275     GST_DEBUG_OBJECT (sinkpad, "activating push");
6276     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6277   }
6278 }
6279
6280 static gboolean
6281 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6282     GstPadMode mode, gboolean active)
6283 {
6284   gboolean res;
6285   GstQTDemux *demux = GST_QTDEMUX (parent);
6286
6287   switch (mode) {
6288     case GST_PAD_MODE_PUSH:
6289       demux->pullbased = FALSE;
6290       res = TRUE;
6291       break;
6292     case GST_PAD_MODE_PULL:
6293       if (active) {
6294         demux->pullbased = TRUE;
6295         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6296             sinkpad, NULL);
6297       } else {
6298         res = gst_pad_stop_task (sinkpad);
6299       }
6300       break;
6301     default:
6302       res = FALSE;
6303       break;
6304   }
6305   return res;
6306 }
6307
6308 #ifdef HAVE_ZLIB
6309 static void *
6310 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6311 {
6312   return g_malloc (items * size);
6313 }
6314
6315 static void
6316 qtdemux_zfree (void *opaque, void *addr)
6317 {
6318   g_free (addr);
6319 }
6320
6321 static void *
6322 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6323 {
6324   guint8 *buffer;
6325   z_stream *z;
6326   int ret;
6327
6328   z = g_new0 (z_stream, 1);
6329   z->zalloc = qtdemux_zalloc;
6330   z->zfree = qtdemux_zfree;
6331   z->opaque = NULL;
6332
6333   z->next_in = z_buffer;
6334   z->avail_in = z_length;
6335
6336   buffer = (guint8 *) g_malloc (length);
6337   ret = inflateInit (z);
6338   while (z->avail_in > 0) {
6339     if (z->avail_out == 0) {
6340       length += 1024;
6341       buffer = (guint8 *) g_realloc (buffer, length);
6342       z->next_out = buffer + z->total_out;
6343       z->avail_out = 1024;
6344     }
6345     ret = inflate (z, Z_SYNC_FLUSH);
6346     if (ret != Z_OK)
6347       break;
6348   }
6349   if (ret != Z_STREAM_END) {
6350     g_warning ("inflate() returned %d", ret);
6351   }
6352
6353   g_free (z);
6354   return buffer;
6355 }
6356 #endif /* HAVE_ZLIB */
6357
6358 static gboolean
6359 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6360 {
6361   GNode *cmov;
6362
6363   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6364
6365   /* counts as header data */
6366   qtdemux->header_size += length;
6367
6368   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6369   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6370
6371   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6372   if (cmov) {
6373     guint32 method;
6374     GNode *dcom;
6375     GNode *cmvd;
6376
6377     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6378     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6379     if (dcom == NULL || cmvd == NULL)
6380       goto invalid_compression;
6381
6382     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6383     switch (method) {
6384 #ifdef HAVE_ZLIB
6385       case FOURCC_zlib:{
6386         guint uncompressed_length;
6387         guint compressed_length;
6388         guint8 *buf;
6389
6390         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6391         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6392         GST_LOG ("length = %u", uncompressed_length);
6393
6394         buf =
6395             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6396             compressed_length, uncompressed_length);
6397
6398         qtdemux->moov_node_compressed = qtdemux->moov_node;
6399         qtdemux->moov_node = g_node_new (buf);
6400
6401         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6402             uncompressed_length);
6403         break;
6404       }
6405 #endif /* HAVE_ZLIB */
6406       default:
6407         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6408             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6409         break;
6410     }
6411   }
6412   return TRUE;
6413
6414   /* ERRORS */
6415 invalid_compression:
6416   {
6417     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6418     return FALSE;
6419   }
6420 }
6421
6422 static gboolean
6423 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6424     const guint8 * end)
6425 {
6426   while (G_UNLIKELY (buf < end)) {
6427     GNode *child;
6428     guint32 len;
6429
6430     if (G_UNLIKELY (buf + 4 > end)) {
6431       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6432       break;
6433     }
6434     len = QT_UINT32 (buf);
6435     if (G_UNLIKELY (len == 0)) {
6436       GST_LOG_OBJECT (qtdemux, "empty container");
6437       break;
6438     }
6439     if (G_UNLIKELY (len < 8)) {
6440       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6441       break;
6442     }
6443     if (G_UNLIKELY (len > (end - buf))) {
6444       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6445           (gint) (end - buf));
6446       break;
6447     }
6448
6449     child = g_node_new ((guint8 *) buf);
6450     g_node_append (node, child);
6451     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6452     qtdemux_parse_node (qtdemux, child, buf, len);
6453
6454     buf += len;
6455   }
6456   return TRUE;
6457 }
6458
6459 static gboolean
6460 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6461     GNode * xdxt)
6462 {
6463   int len = QT_UINT32 (xdxt->data);
6464   guint8 *buf = xdxt->data;
6465   guint8 *end = buf + len;
6466   GstBuffer *buffer;
6467
6468   /* skip size and type */
6469   buf += 8;
6470   end -= 8;
6471
6472   while (buf < end) {
6473     gint size;
6474     guint32 type;
6475
6476     size = QT_UINT32 (buf);
6477     type = QT_FOURCC (buf + 4);
6478
6479     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6480
6481     if (buf + size > end || size <= 0)
6482       break;
6483
6484     buf += 8;
6485     size -= 8;
6486
6487     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6488         GST_FOURCC_ARGS (type));
6489
6490     switch (type) {
6491       case FOURCC_tCtH:
6492         buffer = gst_buffer_new_and_alloc (size);
6493         gst_buffer_fill (buffer, 0, buf, size);
6494         stream->buffers = g_slist_append (stream->buffers, buffer);
6495         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6496         break;
6497       case FOURCC_tCt_:
6498         buffer = gst_buffer_new_and_alloc (size);
6499         gst_buffer_fill (buffer, 0, buf, size);
6500         stream->buffers = g_slist_append (stream->buffers, buffer);
6501         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6502         break;
6503       case FOURCC_tCtC:
6504         buffer = gst_buffer_new_and_alloc (size);
6505         gst_buffer_fill (buffer, 0, buf, size);
6506         stream->buffers = g_slist_append (stream->buffers, buffer);
6507         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6508         break;
6509       default:
6510         GST_WARNING_OBJECT (qtdemux,
6511             "unknown theora cookie %" GST_FOURCC_FORMAT,
6512             GST_FOURCC_ARGS (type));
6513         break;
6514     }
6515     buf += size;
6516   }
6517   return TRUE;
6518 }
6519
6520 static gboolean
6521 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6522     guint length)
6523 {
6524   guint32 fourcc = 0;
6525   guint32 node_length = 0;
6526   const QtNodeType *type;
6527   const guint8 *end;
6528
6529   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6530
6531   if (G_UNLIKELY (length < 8))
6532     goto not_enough_data;
6533
6534   node_length = QT_UINT32 (buffer);
6535   fourcc = QT_FOURCC (buffer + 4);
6536
6537   /* ignore empty nodes */
6538   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6539     return TRUE;
6540
6541   type = qtdemux_type_get (fourcc);
6542
6543   end = buffer + length;
6544
6545   GST_LOG_OBJECT (qtdemux,
6546       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6547       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6548
6549   if (node_length > length)
6550     goto broken_atom_size;
6551
6552   if (type->flags & QT_FLAG_CONTAINER) {
6553     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6554   } else {
6555     switch (fourcc) {
6556       case FOURCC_stsd:
6557       {
6558         if (node_length < 20) {
6559           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6560           break;
6561         }
6562         GST_DEBUG_OBJECT (qtdemux,
6563             "parsing stsd (sample table, sample description) atom");
6564         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6565         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6566         break;
6567       }
6568       case FOURCC_mp4a:
6569       case FOURCC_alac:
6570       {
6571         guint32 version;
6572         guint32 offset;
6573         guint min_size;
6574
6575         /* also read alac (or whatever) in stead of mp4a in the following,
6576          * since a similar layout is used in other cases as well */
6577         if (fourcc == FOURCC_mp4a)
6578           min_size = 20;
6579         else
6580           min_size = 40;
6581
6582         /* There are two things we might encounter here: a true mp4a atom, and
6583            an mp4a entry in an stsd atom. The latter is what we're interested
6584            in, and it looks like an atom, but isn't really one. The true mp4a
6585            atom is short, so we detect it based on length here. */
6586         if (length < min_size) {
6587           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6588               GST_FOURCC_ARGS (fourcc));
6589           break;
6590         }
6591
6592         /* 'version' here is the sound sample description version. Types 0 and
6593            1 are documented in the QTFF reference, but type 2 is not: it's
6594            described in Apple header files instead (struct SoundDescriptionV2
6595            in Movies.h) */
6596         version = QT_UINT16 (buffer + 16);
6597
6598         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6599             GST_FOURCC_ARGS (fourcc), version);
6600
6601         /* parse any esds descriptors */
6602         switch (version) {
6603           case 0:
6604             offset = 0x24;
6605             break;
6606           case 1:
6607             offset = 0x34;
6608             break;
6609           case 2:
6610             offset = 0x48;
6611             break;
6612           default:
6613             GST_WARNING_OBJECT (qtdemux,
6614                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6615                 GST_FOURCC_ARGS (fourcc), version);
6616             offset = 0;
6617             break;
6618         }
6619         if (offset)
6620           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6621         break;
6622       }
6623       case FOURCC_mp4v:
6624       case FOURCC_MP4V:
6625       case FOURCC_fmp4:
6626       case FOURCC_FMP4:
6627       case FOURCC_apcs:
6628       case FOURCC_apch:
6629       case FOURCC_apcn:
6630       case FOURCC_apco:
6631       case FOURCC_ap4h:
6632       {
6633         const guint8 *buf;
6634         guint32 version;
6635         int tlen;
6636
6637         /* codec_data is contained inside these atoms, which all have
6638          * the same format. */
6639
6640         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
6641             GST_FOURCC_ARGS (fourcc));
6642         version = QT_UINT32 (buffer + 16);
6643         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6644         if (1 || version == 0x00000000) {
6645           buf = buffer + 0x32;
6646
6647           /* FIXME Quicktime uses PASCAL string while
6648            * the iso format uses C strings. Check the file
6649            * type before attempting to parse the string here. */
6650           tlen = QT_UINT8 (buf);
6651           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6652           buf++;
6653           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6654           /* the string has a reserved space of 32 bytes so skip
6655            * the remaining 31 */
6656           buf += 31;
6657           buf += 4;             /* and 4 bytes reserved */
6658
6659           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6660
6661           qtdemux_parse_container (qtdemux, node, buf, end);
6662         }
6663         break;
6664       }
6665       case FOURCC_H264:
6666       {
6667         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6668         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6669         break;
6670       }
6671       case FOURCC_avc1:
6672       {
6673         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6674         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6675         break;
6676       }
6677       case FOURCC_avc3:
6678       {
6679         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6680         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6681         break;
6682       }
6683       case FOURCC_H265:
6684       {
6685         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6686         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6687         break;
6688       }
6689       case FOURCC_hvc1:
6690       {
6691         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6692         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6693         break;
6694       }
6695       case FOURCC_hev1:
6696       {
6697         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
6698         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6699         break;
6700       }
6701       case FOURCC_mjp2:
6702       {
6703         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6704         break;
6705       }
6706       case FOURCC_meta:
6707       {
6708         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
6709         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
6710         break;
6711       }
6712       case FOURCC_mp4s:
6713       {
6714         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
6715         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
6716         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6717         break;
6718       }
6719       case FOURCC_XiTh:
6720       {
6721         guint32 version;
6722         guint32 offset;
6723
6724         version = QT_UINT32 (buffer + 12);
6725         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
6726
6727         switch (version) {
6728           case 0x00000001:
6729             offset = 0x62;
6730             break;
6731           default:
6732             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
6733             offset = 0;
6734             break;
6735         }
6736         if (offset)
6737           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6738         break;
6739       }
6740       case FOURCC_in24:
6741       {
6742         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
6743         break;
6744       }
6745       case FOURCC_uuid:
6746       {
6747         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
6748         break;
6749       }
6750       case FOURCC_encv:
6751       {
6752         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6753         break;
6754       }
6755       case FOURCC_enca:
6756       {
6757         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
6758         break;
6759       }
6760       default:
6761         if (!strcmp (type->name, "unknown"))
6762           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
6763         break;
6764     }
6765   }
6766   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
6767       GST_FOURCC_ARGS (fourcc));
6768   return TRUE;
6769
6770 /* ERRORS */
6771 not_enough_data:
6772   {
6773     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6774         (_("This file is corrupt and cannot be played.")),
6775         ("Not enough data for an atom header, got only %u bytes", length));
6776     return FALSE;
6777   }
6778 broken_atom_size:
6779   {
6780     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6781         (_("This file is corrupt and cannot be played.")),
6782         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
6783             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
6784             length));
6785     return FALSE;
6786   }
6787 }
6788
6789 static GNode *
6790 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
6791 {
6792   GNode *child;
6793   guint8 *buffer;
6794   guint32 child_fourcc;
6795
6796   for (child = g_node_first_child (node); child;
6797       child = g_node_next_sibling (child)) {
6798     buffer = (guint8 *) child->data;
6799
6800     child_fourcc = QT_FOURCC (buffer + 4);
6801
6802     if (G_UNLIKELY (child_fourcc == fourcc)) {
6803       return child;
6804     }
6805   }
6806   return NULL;
6807 }
6808
6809 static GNode *
6810 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
6811     GstByteReader * parser)
6812 {
6813   GNode *child;
6814   guint8 *buffer;
6815   guint32 child_fourcc, child_len;
6816
6817   for (child = g_node_first_child (node); child;
6818       child = g_node_next_sibling (child)) {
6819     buffer = (guint8 *) child->data;
6820
6821     child_len = QT_UINT32 (buffer);
6822     child_fourcc = QT_FOURCC (buffer + 4);
6823
6824     if (G_UNLIKELY (child_fourcc == fourcc)) {
6825       if (G_UNLIKELY (child_len < (4 + 4)))
6826         return NULL;
6827       /* FIXME: must verify if atom length < parent atom length */
6828       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6829       return child;
6830     }
6831   }
6832   return NULL;
6833 }
6834
6835 static GNode *
6836 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
6837     GstByteReader * parser)
6838 {
6839   GNode *child;
6840   guint8 *buffer;
6841   guint32 child_fourcc, child_len;
6842
6843   for (child = g_node_next_sibling (node); child;
6844       child = g_node_next_sibling (child)) {
6845     buffer = (guint8 *) child->data;
6846
6847     child_fourcc = QT_FOURCC (buffer + 4);
6848
6849     if (child_fourcc == fourcc) {
6850       if (parser) {
6851         child_len = QT_UINT32 (buffer);
6852         if (G_UNLIKELY (child_len < (4 + 4)))
6853           return NULL;
6854         /* FIXME: must verify if atom length < parent atom length */
6855         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6856       }
6857       return child;
6858     }
6859   }
6860   return NULL;
6861 }
6862
6863 static GNode *
6864 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
6865 {
6866   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
6867 }
6868
6869 static void
6870 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
6871 {
6872 /* FIXME: This can only reliably work if demuxers have a
6873  * separate streaming thread per srcpad. This should be
6874  * done in a demuxer base class, which integrates parts
6875  * of multiqueue
6876  *
6877  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
6878  */
6879 #if 0
6880   GstQuery *query;
6881
6882   query = gst_query_new_allocation (stream->caps, FALSE);
6883
6884   if (!gst_pad_peer_query (stream->pad, query)) {
6885     /* not a problem, just debug a little */
6886     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
6887   }
6888
6889   if (stream->allocator)
6890     gst_object_unref (stream->allocator);
6891
6892   if (gst_query_get_n_allocation_params (query) > 0) {
6893     /* try the allocator */
6894     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
6895         &stream->params);
6896     stream->use_allocator = TRUE;
6897   } else {
6898     stream->allocator = NULL;
6899     gst_allocation_params_init (&stream->params);
6900     stream->use_allocator = FALSE;
6901   }
6902   gst_query_unref (query);
6903 #endif
6904 }
6905
6906 static gboolean
6907 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
6908     QtDemuxStream * stream)
6909 {
6910   GstStructure *s;
6911   const gchar *selected_system;
6912
6913   g_return_val_if_fail (qtdemux != NULL, FALSE);
6914   g_return_val_if_fail (stream != NULL, FALSE);
6915   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
6916
6917   if (stream->protection_scheme_type != FOURCC_cenc) {
6918     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
6919     return FALSE;
6920   }
6921   if (qtdemux->protection_system_ids == NULL) {
6922     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
6923         "cenc protection system information has been found");
6924     return FALSE;
6925   }
6926   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
6927   selected_system = gst_protection_select_system ((const gchar **)
6928       qtdemux->protection_system_ids->pdata);
6929   g_ptr_array_remove_index (qtdemux->protection_system_ids,
6930       qtdemux->protection_system_ids->len - 1);
6931   if (!selected_system) {
6932     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
6933         "suitable decryptor element has been found");
6934     return FALSE;
6935   }
6936
6937   s = gst_caps_get_structure (stream->caps, 0);
6938   gst_structure_set (s,
6939       "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
6940       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
6941       NULL);
6942   gst_structure_set_name (s, "application/x-cenc");
6943   return TRUE;
6944 }
6945
6946 static gboolean
6947 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
6948 {
6949   if (stream->subtype == FOURCC_vide) {
6950     /* fps is calculated base on the duration of the average framerate since
6951      * qt does not have a fixed framerate. */
6952     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
6953       /* still frame */
6954       stream->fps_n = 0;
6955       stream->fps_d = 1;
6956     } else {
6957       if (stream->duration == 0 || stream->n_samples < 2) {
6958         stream->fps_n = stream->timescale;
6959         stream->fps_d = 1;
6960       } else {
6961         GstClockTime avg_duration;
6962         guint64 duration;
6963         guint32 n_samples;
6964
6965         /* duration and n_samples can be updated for fragmented format
6966          * so, framerate of fragmented format is calculated using data in a moof */
6967         if (qtdemux->fragmented && stream->n_samples_moof > 0
6968             && stream->duration_moof > 0) {
6969           n_samples = stream->n_samples_moof;
6970           duration = stream->duration_moof;
6971         } else {
6972           n_samples = stream->n_samples;
6973           duration = stream->duration;
6974         }
6975
6976         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
6977         /* stream->duration is guint64, timescale, n_samples are guint32 */
6978         avg_duration =
6979             gst_util_uint64_scale_round (duration -
6980             stream->first_duration, GST_SECOND,
6981             (guint64) (stream->timescale) * (n_samples - 1));
6982
6983         GST_LOG_OBJECT (qtdemux,
6984             "Calculating avg sample duration based on stream (or moof) duration %"
6985             G_GUINT64_FORMAT
6986             " minus first sample %u, leaving %d samples gives %"
6987             GST_TIME_FORMAT, duration, stream->first_duration,
6988             n_samples - 1, GST_TIME_ARGS (avg_duration));
6989
6990         gst_video_guess_framerate (avg_duration, &stream->fps_n,
6991             &stream->fps_d);
6992       }
6993       GST_DEBUG_OBJECT (qtdemux,
6994           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
6995           stream->timescale, stream->fps_n, stream->fps_d);
6996     }
6997
6998     if (stream->caps) {
6999       stream->caps = gst_caps_make_writable (stream->caps);
7000
7001       gst_caps_set_simple (stream->caps,
7002           "width", G_TYPE_INT, stream->width,
7003           "height", G_TYPE_INT, stream->height,
7004           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7005
7006       /* calculate pixel-aspect-ratio using display width and height */
7007       GST_DEBUG_OBJECT (qtdemux,
7008           "video size %dx%d, target display size %dx%d", stream->width,
7009           stream->height, stream->display_width, stream->display_height);
7010       /* qt file might have pasp atom */
7011       if (stream->par_w > 0 && stream->par_h > 0) {
7012         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7013         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7014             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7015       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7016           stream->width > 0 && stream->height > 0) {
7017         gint n, d;
7018
7019         /* calculate the pixel aspect ratio using the display and pixel w/h */
7020         n = stream->display_width * stream->height;
7021         d = stream->display_height * stream->width;
7022         if (n == d)
7023           n = d = 1;
7024         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7025         stream->par_w = n;
7026         stream->par_h = d;
7027         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7028             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7029       }
7030
7031       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7032         guint par_w = 1, par_h = 1;
7033
7034         if (stream->par_w > 0 && stream->par_h > 0) {
7035           par_w = stream->par_w;
7036           par_h = stream->par_h;
7037         }
7038
7039         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7040                 stream->width, stream->height, par_w, par_h)) {
7041           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7042         }
7043
7044         gst_caps_set_simple (stream->caps,
7045             "multiview-mode", G_TYPE_STRING,
7046             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7047             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7048             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7049       }
7050     }
7051   }
7052
7053   else if (stream->subtype == FOURCC_soun) {
7054     if (stream->caps) {
7055       stream->caps = gst_caps_make_writable (stream->caps);
7056       if (stream->rate > 0)
7057         gst_caps_set_simple (stream->caps,
7058             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7059       if (stream->n_channels > 0)
7060         gst_caps_set_simple (stream->caps,
7061             "channels", G_TYPE_INT, stream->n_channels, NULL);
7062       if (stream->n_channels > 2) {
7063         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7064          * correctly; this is just the minimum we can do - assume
7065          * we don't actually have any channel positions. */
7066         gst_caps_set_simple (stream->caps,
7067             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7068       }
7069     }
7070   }
7071
7072   if (stream->pad) {
7073     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7074     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7075     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7076     gst_pad_set_active (stream->pad, TRUE);
7077
7078     gst_pad_use_fixed_caps (stream->pad);
7079
7080     if (stream->protected) {
7081       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7082         GST_ERROR_OBJECT (qtdemux,
7083             "Failed to configure protected stream caps.");
7084         return FALSE;
7085       }
7086     }
7087
7088     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7089     if (stream->new_stream) {
7090       gchar *stream_id;
7091       GstEvent *event;
7092       GstStreamFlags stream_flags;
7093
7094       event =
7095           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7096           0);
7097       if (event) {
7098         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7099           qtdemux->have_group_id = TRUE;
7100         else
7101           qtdemux->have_group_id = FALSE;
7102         gst_event_unref (event);
7103       } else if (!qtdemux->have_group_id) {
7104         qtdemux->have_group_id = TRUE;
7105         qtdemux->group_id = gst_util_group_id_next ();
7106       }
7107
7108       stream->new_stream = FALSE;
7109       stream_id =
7110           gst_pad_create_stream_id_printf (stream->pad,
7111           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7112       event = gst_event_new_stream_start (stream_id);
7113       if (qtdemux->have_group_id)
7114         gst_event_set_group_id (event, qtdemux->group_id);
7115       stream_flags = GST_STREAM_FLAG_NONE;
7116       if (stream->disabled)
7117         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7118       if (stream->sparse)
7119         stream_flags |= GST_STREAM_FLAG_SPARSE;
7120       gst_event_set_stream_flags (event, stream_flags);
7121       gst_pad_push_event (stream->pad, event);
7122       g_free (stream_id);
7123     }
7124     gst_pad_set_caps (stream->pad, stream->caps);
7125     stream->new_caps = FALSE;
7126   }
7127   return TRUE;
7128 }
7129
7130 static gboolean
7131 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7132     QtDemuxStream * stream, GstTagList * list)
7133 {
7134   /* consistent default for push based mode */
7135   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7136
7137   if (stream->subtype == FOURCC_vide) {
7138     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7139
7140     stream->pad =
7141         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7142     g_free (name);
7143
7144     gst_qtdemux_configure_stream (qtdemux, stream);
7145     qtdemux->n_video_streams++;
7146   } else if (stream->subtype == FOURCC_soun) {
7147     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7148
7149     stream->pad =
7150         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7151     g_free (name);
7152     gst_qtdemux_configure_stream (qtdemux, stream);
7153     qtdemux->n_audio_streams++;
7154   } else if (stream->subtype == FOURCC_strm) {
7155     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7156   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7157       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7158     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7159
7160     stream->pad =
7161         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7162     g_free (name);
7163     gst_qtdemux_configure_stream (qtdemux, stream);
7164     qtdemux->n_sub_streams++;
7165   } else if (stream->caps) {
7166     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7167
7168     stream->pad =
7169         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7170     g_free (name);
7171     gst_qtdemux_configure_stream (qtdemux, stream);
7172     qtdemux->n_video_streams++;
7173   } else {
7174     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7175     goto done;
7176   }
7177
7178   if (stream->pad) {
7179     GList *l;
7180
7181     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7182         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7183     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7184     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7185
7186     if (stream->pending_tags)
7187       gst_tag_list_unref (stream->pending_tags);
7188     stream->pending_tags = list;
7189     list = NULL;
7190     /* global tags go on each pad anyway */
7191     stream->send_global_tags = TRUE;
7192     /* send upstream GST_EVENT_PROTECTION events that were received before
7193        this source pad was created */
7194     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7195       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7196   }
7197 done:
7198   if (list)
7199     gst_tag_list_unref (list);
7200   return TRUE;
7201 }
7202
7203 /* find next atom with @fourcc starting at @offset */
7204 static GstFlowReturn
7205 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7206     guint64 * length, guint32 fourcc)
7207 {
7208   GstFlowReturn ret;
7209   guint32 lfourcc;
7210   GstBuffer *buf;
7211
7212   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7213       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7214
7215   while (TRUE) {
7216     GstMapInfo map;
7217
7218     buf = NULL;
7219     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7220     if (G_UNLIKELY (ret != GST_FLOW_OK))
7221       goto locate_failed;
7222     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7223       /* likely EOF */
7224       ret = GST_FLOW_EOS;
7225       gst_buffer_unref (buf);
7226       goto locate_failed;
7227     }
7228     gst_buffer_map (buf, &map, GST_MAP_READ);
7229     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7230     gst_buffer_unmap (buf, &map);
7231     gst_buffer_unref (buf);
7232
7233     if (G_UNLIKELY (*length == 0)) {
7234       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7235       ret = GST_FLOW_ERROR;
7236       goto locate_failed;
7237     }
7238
7239     if (lfourcc == fourcc) {
7240       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7241           *offset);
7242       break;
7243     } else {
7244       GST_LOG_OBJECT (qtdemux,
7245           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7246           GST_FOURCC_ARGS (fourcc), *offset);
7247       *offset += *length;
7248     }
7249   }
7250
7251   return GST_FLOW_OK;
7252
7253 locate_failed:
7254   {
7255     /* might simply have had last one */
7256     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7257     return ret;
7258   }
7259 }
7260
7261 /* should only do something in pull mode */
7262 /* call with OBJECT lock */
7263 static GstFlowReturn
7264 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7265 {
7266   guint64 length, offset;
7267   GstBuffer *buf = NULL;
7268   GstFlowReturn ret = GST_FLOW_OK;
7269   GstFlowReturn res = GST_FLOW_OK;
7270   GstMapInfo map;
7271
7272   offset = qtdemux->moof_offset;
7273   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7274
7275   if (!offset) {
7276     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7277     return GST_FLOW_EOS;
7278   }
7279
7280   /* best not do pull etc with lock held */
7281   GST_OBJECT_UNLOCK (qtdemux);
7282
7283   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7284   if (ret != GST_FLOW_OK)
7285     goto flow_failed;
7286
7287   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7288   if (G_UNLIKELY (ret != GST_FLOW_OK))
7289     goto flow_failed;
7290   gst_buffer_map (buf, &map, GST_MAP_READ);
7291   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7292     gst_buffer_unmap (buf, &map);
7293     gst_buffer_unref (buf);
7294     buf = NULL;
7295     goto parse_failed;
7296   }
7297
7298   gst_buffer_unmap (buf, &map);
7299   gst_buffer_unref (buf);
7300   buf = NULL;
7301
7302   offset += length;
7303   /* look for next moof */
7304   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7305   if (G_UNLIKELY (ret != GST_FLOW_OK))
7306     goto flow_failed;
7307
7308 exit:
7309   GST_OBJECT_LOCK (qtdemux);
7310
7311   qtdemux->moof_offset = offset;
7312
7313   return res;
7314
7315 parse_failed:
7316   {
7317     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7318     offset = 0;
7319     res = GST_FLOW_ERROR;
7320     goto exit;
7321   }
7322 flow_failed:
7323   {
7324     /* maybe upstream temporarily flushing */
7325     if (ret != GST_FLOW_FLUSHING) {
7326       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7327       offset = 0;
7328     } else {
7329       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7330       /* resume at current position next time */
7331     }
7332     res = ret;
7333     goto exit;
7334   }
7335 }
7336
7337 /* initialise bytereaders for stbl sub-atoms */
7338 static gboolean
7339 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7340 {
7341   stream->stbl_index = -1;      /* no samples have yet been parsed */
7342   stream->sample_index = -1;
7343
7344   /* time-to-sample atom */
7345   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7346     goto corrupt_file;
7347
7348   /* copy atom data into a new buffer for later use */
7349   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7350
7351   /* skip version + flags */
7352   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7353       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7354     goto corrupt_file;
7355   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7356
7357   /* make sure there's enough data */
7358   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7359     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7360     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7361         stream->n_sample_times);
7362     if (!stream->n_sample_times)
7363       goto corrupt_file;
7364   }
7365
7366   /* sync sample atom */
7367   stream->stps_present = FALSE;
7368   if ((stream->stss_present =
7369           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7370               &stream->stss) ? TRUE : FALSE) == TRUE) {
7371     /* copy atom data into a new buffer for later use */
7372     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7373
7374     /* skip version + flags */
7375     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7376         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7377       goto corrupt_file;
7378
7379     if (stream->n_sample_syncs) {
7380       /* make sure there's enough data */
7381       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7382         goto corrupt_file;
7383     }
7384
7385     /* partial sync sample atom */
7386     if ((stream->stps_present =
7387             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7388                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7389       /* copy atom data into a new buffer for later use */
7390       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7391
7392       /* skip version + flags */
7393       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7394           !gst_byte_reader_get_uint32_be (&stream->stps,
7395               &stream->n_sample_partial_syncs))
7396         goto corrupt_file;
7397
7398       /* if there are no entries, the stss table contains the real
7399        * sync samples */
7400       if (stream->n_sample_partial_syncs) {
7401         /* make sure there's enough data */
7402         if (!qt_atom_parser_has_chunks (&stream->stps,
7403                 stream->n_sample_partial_syncs, 4))
7404           goto corrupt_file;
7405       }
7406     }
7407   }
7408
7409   /* sample size */
7410   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7411     goto no_samples;
7412
7413   /* copy atom data into a new buffer for later use */
7414   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7415
7416   /* skip version + flags */
7417   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7418       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7419     goto corrupt_file;
7420
7421   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7422     goto corrupt_file;
7423
7424   if (!stream->n_samples)
7425     goto no_samples;
7426
7427   /* sample-to-chunk atom */
7428   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7429     goto corrupt_file;
7430
7431   /* copy atom data into a new buffer for later use */
7432   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7433
7434   /* skip version + flags */
7435   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7436       !gst_byte_reader_get_uint32_be (&stream->stsc,
7437           &stream->n_samples_per_chunk))
7438     goto corrupt_file;
7439
7440   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7441       stream->n_samples_per_chunk);
7442
7443   /* make sure there's enough data */
7444   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7445           12))
7446     goto corrupt_file;
7447
7448
7449   /* chunk offset */
7450   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7451     stream->co_size = sizeof (guint32);
7452   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7453           &stream->stco))
7454     stream->co_size = sizeof (guint64);
7455   else
7456     goto corrupt_file;
7457
7458   /* copy atom data into a new buffer for later use */
7459   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7460
7461   /* skip version + flags */
7462   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7463     goto corrupt_file;
7464
7465   /* chunks_are_samples == TRUE means treat chunks as samples */
7466   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7467   if (stream->chunks_are_samples) {
7468     /* treat chunks as samples */
7469     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7470       goto corrupt_file;
7471   } else {
7472     /* skip number of entries */
7473     if (!gst_byte_reader_skip (&stream->stco, 4))
7474       goto corrupt_file;
7475
7476     /* make sure there are enough data in the stsz atom */
7477     if (!stream->sample_size) {
7478       /* different sizes for each sample */
7479       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7480         goto corrupt_file;
7481     }
7482   }
7483
7484   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7485       stream->n_samples, (guint) sizeof (QtDemuxSample),
7486       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7487
7488   if (stream->n_samples >=
7489       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7490     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7491         "be larger than %uMB (broken file?)", stream->n_samples,
7492         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7493     return FALSE;
7494   }
7495
7496   g_assert (stream->samples == NULL);
7497   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7498   if (!stream->samples) {
7499     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7500         stream->n_samples);
7501     return FALSE;
7502   }
7503
7504   /* composition time-to-sample */
7505   if ((stream->ctts_present =
7506           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7507               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7508     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7509
7510     /* copy atom data into a new buffer for later use */
7511     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7512
7513     /* skip version + flags */
7514     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7515         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7516             &stream->n_composition_times))
7517       goto corrupt_file;
7518
7519     /* make sure there's enough data */
7520     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7521             4 + 4))
7522       goto corrupt_file;
7523
7524     /* This is optional, if missing we iterate the ctts */
7525     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7526       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7527           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7528         g_free ((gpointer) cslg.data);
7529         goto corrupt_file;
7530       }
7531     } else {
7532       gint32 cslg_least = 0;
7533       guint num_entries, pos;
7534       gint i;
7535
7536       pos = gst_byte_reader_get_pos (&stream->ctts);
7537       num_entries = stream->n_composition_times;
7538
7539       stream->cslg_shift = 0;
7540
7541       for (i = 0; i < num_entries; i++) {
7542         gint32 offset;
7543
7544         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7545         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7546
7547         if (offset < cslg_least)
7548           cslg_least = offset;
7549       }
7550
7551       if (cslg_least < 0)
7552         stream->cslg_shift = ABS (cslg_least);
7553       else
7554         stream->cslg_shift = 0;
7555
7556       /* reset the reader so we can generate sample table */
7557       gst_byte_reader_set_pos (&stream->ctts, pos);
7558     }
7559   } else {
7560     /* Ensure the cslg_shift value is consistent so we can use it
7561      * unconditionnally to produce TS and Segment */
7562     stream->cslg_shift = 0;
7563   }
7564
7565   return TRUE;
7566
7567 corrupt_file:
7568   {
7569     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7570         (_("This file is corrupt and cannot be played.")), (NULL));
7571     return FALSE;
7572   }
7573 no_samples:
7574   {
7575     gst_qtdemux_stbl_free (stream);
7576     if (!qtdemux->fragmented) {
7577       /* not quite good */
7578       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7579       return FALSE;
7580     } else {
7581       /* may pick up samples elsewhere */
7582       return TRUE;
7583     }
7584   }
7585 }
7586
7587 /* collect samples from the next sample to be parsed up to sample @n for @stream
7588  * by reading the info from @stbl
7589  *
7590  * This code can be executed from both the streaming thread and the seeking
7591  * thread so it takes the object lock to protect itself
7592  */
7593 static gboolean
7594 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
7595 {
7596   gint i, j, k;
7597   QtDemuxSample *samples, *first, *cur, *last;
7598   guint32 n_samples_per_chunk;
7599   guint32 n_samples;
7600
7601   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
7602       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
7603       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
7604
7605   n_samples = stream->n_samples;
7606
7607   if (n >= n_samples)
7608     goto out_of_samples;
7609
7610   GST_OBJECT_LOCK (qtdemux);
7611   if (n <= stream->stbl_index)
7612     goto already_parsed;
7613
7614   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
7615
7616   if (!stream->stsz.data) {
7617     /* so we already parsed and passed all the moov samples;
7618      * onto fragmented ones */
7619     g_assert (qtdemux->fragmented);
7620     goto done;
7621   }
7622
7623   /* pointer to the sample table */
7624   samples = stream->samples;
7625
7626   /* starts from -1, moves to the next sample index to parse */
7627   stream->stbl_index++;
7628
7629   /* keep track of the first and last sample to fill */
7630   first = &samples[stream->stbl_index];
7631   last = &samples[n];
7632
7633   if (!stream->chunks_are_samples) {
7634     /* set the sample sizes */
7635     if (stream->sample_size == 0) {
7636       /* different sizes for each sample */
7637       for (cur = first; cur <= last; cur++) {
7638         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
7639         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
7640             (guint) (cur - samples), cur->size);
7641       }
7642     } else {
7643       /* samples have the same size */
7644       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
7645       for (cur = first; cur <= last; cur++)
7646         cur->size = stream->sample_size;
7647     }
7648   }
7649
7650   n_samples_per_chunk = stream->n_samples_per_chunk;
7651   cur = first;
7652
7653   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
7654     guint32 last_chunk;
7655
7656     if (stream->stsc_chunk_index >= stream->last_chunk
7657         || stream->stsc_chunk_index < stream->first_chunk) {
7658       stream->first_chunk =
7659           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7660       stream->samples_per_chunk =
7661           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7662       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
7663
7664       /* chunk numbers are counted from 1 it seems */
7665       if (G_UNLIKELY (stream->first_chunk == 0))
7666         goto corrupt_file;
7667
7668       --stream->first_chunk;
7669
7670       /* the last chunk of each entry is calculated by taking the first chunk
7671        * of the next entry; except if there is no next, where we fake it with
7672        * INT_MAX */
7673       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
7674         stream->last_chunk = G_MAXUINT32;
7675       } else {
7676         stream->last_chunk =
7677             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
7678         if (G_UNLIKELY (stream->last_chunk == 0))
7679           goto corrupt_file;
7680
7681         --stream->last_chunk;
7682       }
7683
7684       GST_LOG_OBJECT (qtdemux,
7685           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
7686           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
7687
7688       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
7689         goto corrupt_file;
7690
7691       if (stream->last_chunk != G_MAXUINT32) {
7692         if (!qt_atom_parser_peek_sub (&stream->stco,
7693                 stream->first_chunk * stream->co_size,
7694                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
7695                 &stream->co_chunk))
7696           goto corrupt_file;
7697
7698       } else {
7699         stream->co_chunk = stream->stco;
7700         if (!gst_byte_reader_skip (&stream->co_chunk,
7701                 stream->first_chunk * stream->co_size))
7702           goto corrupt_file;
7703       }
7704
7705       stream->stsc_chunk_index = stream->first_chunk;
7706     }
7707
7708     last_chunk = stream->last_chunk;
7709
7710     if (stream->chunks_are_samples) {
7711       cur = &samples[stream->stsc_chunk_index];
7712
7713       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7714         if (j > n) {
7715           /* save state */
7716           stream->stsc_chunk_index = j;
7717           goto done;
7718         }
7719
7720         cur->offset =
7721             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
7722             stream->co_size);
7723
7724         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
7725             "%" G_GUINT64_FORMAT, j, cur->offset);
7726
7727         if (stream->samples_per_frame * stream->bytes_per_frame) {
7728           cur->size =
7729               (stream->samples_per_chunk * stream->n_channels) /
7730               stream->samples_per_frame * stream->bytes_per_frame;
7731         } else {
7732           cur->size = stream->samples_per_chunk;
7733         }
7734
7735         GST_DEBUG_OBJECT (qtdemux,
7736             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
7737             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
7738                     stream->stco_sample_index)), cur->size);
7739
7740         cur->timestamp = stream->stco_sample_index;
7741         cur->duration = stream->samples_per_chunk;
7742         cur->keyframe = TRUE;
7743         cur++;
7744
7745         stream->stco_sample_index += stream->samples_per_chunk;
7746       }
7747       stream->stsc_chunk_index = j;
7748     } else {
7749       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7750         guint32 samples_per_chunk;
7751         guint64 chunk_offset;
7752
7753         if (!stream->stsc_sample_index
7754             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
7755                 &stream->chunk_offset))
7756           goto corrupt_file;
7757
7758         samples_per_chunk = stream->samples_per_chunk;
7759         chunk_offset = stream->chunk_offset;
7760
7761         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
7762           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
7763               G_GUINT64_FORMAT " and size %d",
7764               (guint) (cur - samples), chunk_offset, cur->size);
7765
7766           cur->offset = chunk_offset;
7767           chunk_offset += cur->size;
7768           cur++;
7769
7770           if (G_UNLIKELY (cur > last)) {
7771             /* save state */
7772             stream->stsc_sample_index = k + 1;
7773             stream->chunk_offset = chunk_offset;
7774             stream->stsc_chunk_index = j;
7775             goto done2;
7776           }
7777         }
7778         stream->stsc_sample_index = 0;
7779       }
7780       stream->stsc_chunk_index = j;
7781     }
7782     stream->stsc_index++;
7783   }
7784
7785   if (stream->chunks_are_samples)
7786     goto ctts;
7787 done2:
7788   {
7789     guint32 n_sample_times;
7790
7791     n_sample_times = stream->n_sample_times;
7792     cur = first;
7793
7794     for (i = stream->stts_index; i < n_sample_times; i++) {
7795       guint32 stts_samples;
7796       gint32 stts_duration;
7797       gint64 stts_time;
7798
7799       if (stream->stts_sample_index >= stream->stts_samples
7800           || !stream->stts_sample_index) {
7801
7802         stream->stts_samples =
7803             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7804         stream->stts_duration =
7805             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7806
7807         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
7808             i, stream->stts_samples, stream->stts_duration);
7809
7810         stream->stts_sample_index = 0;
7811       }
7812
7813       stts_samples = stream->stts_samples;
7814       stts_duration = stream->stts_duration;
7815       stts_time = stream->stts_time;
7816
7817       for (j = stream->stts_sample_index; j < stts_samples; j++) {
7818         GST_DEBUG_OBJECT (qtdemux,
7819             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
7820             (guint) (cur - samples), j,
7821             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
7822
7823         cur->timestamp = stts_time;
7824         cur->duration = stts_duration;
7825
7826         /* avoid 32-bit wrap-around,
7827          * but still mind possible 'negative' duration */
7828         stts_time += (gint64) stts_duration;
7829         cur++;
7830
7831         if (G_UNLIKELY (cur > last)) {
7832           /* save values */
7833           stream->stts_time = stts_time;
7834           stream->stts_sample_index = j + 1;
7835           goto done3;
7836         }
7837       }
7838       stream->stts_sample_index = 0;
7839       stream->stts_time = stts_time;
7840       stream->stts_index++;
7841     }
7842     /* fill up empty timestamps with the last timestamp, this can happen when
7843      * the last samples do not decode and so we don't have timestamps for them.
7844      * We however look at the last timestamp to estimate the track length so we
7845      * need something in here. */
7846     for (; cur < last; cur++) {
7847       GST_DEBUG_OBJECT (qtdemux,
7848           "fill sample %d: timestamp %" GST_TIME_FORMAT,
7849           (guint) (cur - samples),
7850           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
7851       cur->timestamp = stream->stts_time;
7852       cur->duration = -1;
7853     }
7854   }
7855 done3:
7856   {
7857     /* sample sync, can be NULL */
7858     if (stream->stss_present == TRUE) {
7859       guint32 n_sample_syncs;
7860
7861       n_sample_syncs = stream->n_sample_syncs;
7862
7863       if (!n_sample_syncs) {
7864         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
7865         stream->all_keyframe = TRUE;
7866       } else {
7867         for (i = stream->stss_index; i < n_sample_syncs; i++) {
7868           /* note that the first sample is index 1, not 0 */
7869           guint32 index;
7870
7871           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
7872
7873           if (G_LIKELY (index > 0 && index <= n_samples)) {
7874             index -= 1;
7875             samples[index].keyframe = TRUE;
7876             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7877             /* and exit if we have enough samples */
7878             if (G_UNLIKELY (index >= n)) {
7879               i++;
7880               break;
7881             }
7882           }
7883         }
7884         /* save state */
7885         stream->stss_index = i;
7886       }
7887
7888       /* stps marks partial sync frames like open GOP I-Frames */
7889       if (stream->stps_present == TRUE) {
7890         guint32 n_sample_partial_syncs;
7891
7892         n_sample_partial_syncs = stream->n_sample_partial_syncs;
7893
7894         /* if there are no entries, the stss table contains the real
7895          * sync samples */
7896         if (n_sample_partial_syncs) {
7897           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
7898             /* note that the first sample is index 1, not 0 */
7899             guint32 index;
7900
7901             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
7902
7903             if (G_LIKELY (index > 0 && index <= n_samples)) {
7904               index -= 1;
7905               samples[index].keyframe = TRUE;
7906               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7907               /* and exit if we have enough samples */
7908               if (G_UNLIKELY (index >= n)) {
7909                 i++;
7910                 break;
7911               }
7912             }
7913           }
7914           /* save state */
7915           stream->stps_index = i;
7916         }
7917       }
7918     } else {
7919       /* no stss, all samples are keyframes */
7920       stream->all_keyframe = TRUE;
7921       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
7922     }
7923   }
7924
7925 ctts:
7926   /* composition time to sample */
7927   if (stream->ctts_present == TRUE) {
7928     guint32 n_composition_times;
7929     guint32 ctts_count;
7930     gint32 ctts_soffset;
7931
7932     /* Fill in the pts_offsets */
7933     cur = first;
7934     n_composition_times = stream->n_composition_times;
7935
7936     for (i = stream->ctts_index; i < n_composition_times; i++) {
7937       if (stream->ctts_sample_index >= stream->ctts_count
7938           || !stream->ctts_sample_index) {
7939         stream->ctts_count =
7940             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
7941         stream->ctts_soffset =
7942             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7943         stream->ctts_sample_index = 0;
7944       }
7945
7946       ctts_count = stream->ctts_count;
7947       ctts_soffset = stream->ctts_soffset;
7948
7949       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
7950         cur->pts_offset = ctts_soffset;
7951         cur++;
7952
7953         if (G_UNLIKELY (cur > last)) {
7954           /* save state */
7955           stream->ctts_sample_index = j + 1;
7956           goto done;
7957         }
7958       }
7959       stream->ctts_sample_index = 0;
7960       stream->ctts_index++;
7961     }
7962   }
7963 done:
7964   stream->stbl_index = n;
7965   /* if index has been completely parsed, free data that is no-longer needed */
7966   if (n + 1 == stream->n_samples) {
7967     gst_qtdemux_stbl_free (stream);
7968     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
7969     if (qtdemux->pullbased) {
7970       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
7971       while (n + 1 == stream->n_samples)
7972         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
7973           break;
7974     }
7975   }
7976   GST_OBJECT_UNLOCK (qtdemux);
7977
7978   return TRUE;
7979
7980   /* SUCCESS */
7981 already_parsed:
7982   {
7983     GST_LOG_OBJECT (qtdemux,
7984         "Tried to parse up to sample %u but this sample has already been parsed",
7985         n);
7986     /* if fragmented, there may be more */
7987     if (qtdemux->fragmented && n == stream->stbl_index)
7988       goto done;
7989     GST_OBJECT_UNLOCK (qtdemux);
7990     return TRUE;
7991   }
7992   /* ERRORS */
7993 out_of_samples:
7994   {
7995     GST_LOG_OBJECT (qtdemux,
7996         "Tried to parse up to sample %u but there are only %u samples", n + 1,
7997         stream->n_samples);
7998     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7999         (_("This file is corrupt and cannot be played.")), (NULL));
8000     return FALSE;
8001   }
8002 corrupt_file:
8003   {
8004     GST_OBJECT_UNLOCK (qtdemux);
8005     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8006         (_("This file is corrupt and cannot be played.")), (NULL));
8007     return FALSE;
8008   }
8009 }
8010
8011 /* collect all segment info for @stream.
8012  */
8013 static gboolean
8014 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8015     GNode * trak)
8016 {
8017   GNode *edts;
8018   /* accept edts if they contain gaps at start and there is only
8019    * one media segment */
8020   gboolean allow_pushbased_edts = TRUE;
8021   gint media_segments_count = 0;
8022
8023   /* parse and prepare segment info from the edit list */
8024   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8025   stream->n_segments = 0;
8026   stream->segments = NULL;
8027   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8028     GNode *elst;
8029     gint n_segments;
8030     gint i, count;
8031     guint64 time;
8032     GstClockTime stime;
8033     guint8 *buffer;
8034
8035     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8036     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8037       goto done;
8038
8039     buffer = elst->data;
8040
8041     n_segments = QT_UINT32 (buffer + 12);
8042
8043     /* we might allocate a bit too much, at least allocate 1 segment */
8044     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8045
8046     /* segments always start from 0 */
8047     time = 0;
8048     stime = 0;
8049     count = 0;
8050     for (i = 0; i < n_segments; i++) {
8051       guint64 duration;
8052       guint64 media_time;
8053       QtDemuxSegment *segment;
8054       guint32 rate_int;
8055       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8056
8057       media_time = QT_UINT32 (buffer + 20 + i * 12);
8058       duration = QT_UINT32 (buffer + 16 + i * 12);
8059
8060       if (media_time != G_MAXUINT32)
8061         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8062
8063       segment = &stream->segments[count++];
8064
8065       /* time and duration expressed in global timescale */
8066       segment->time = stime;
8067       /* add non scaled values so we don't cause roundoff errors */
8068       if (duration) {
8069         time += duration;
8070         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8071         segment->duration = stime - segment->time;
8072       } else {
8073         /* zero duration does not imply media_start == media_stop
8074          * but, only specify media_start.*/
8075         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8076         if (GST_CLOCK_TIME_IS_VALID (stime) && media_time != G_MAXUINT32
8077             && stime >= media_start) {
8078           segment->duration = stime - media_start;
8079         } else {
8080           segment->duration = GST_CLOCK_TIME_NONE;
8081         }
8082       }
8083       segment->stop_time = stime;
8084
8085       segment->trak_media_start = media_time;
8086       /* media_time expressed in stream timescale */
8087       if (media_time != G_MAXUINT32) {
8088         segment->media_start = media_start;
8089         segment->media_stop = segment->media_start + segment->duration;
8090         media_segments_count++;
8091       } else {
8092         segment->media_start = GST_CLOCK_TIME_NONE;
8093         segment->media_stop = GST_CLOCK_TIME_NONE;
8094       }
8095       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
8096
8097       if (rate_int <= 1) {
8098         /* 0 is not allowed, some programs write 1 instead of the floating point
8099          * value */
8100         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8101             rate_int);
8102         segment->rate = 1;
8103       } else {
8104         segment->rate = rate_int / 65536.0;
8105       }
8106
8107       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8108           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8109           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8110           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8111           i, GST_TIME_ARGS (segment->time),
8112           GST_TIME_ARGS (segment->duration),
8113           GST_TIME_ARGS (segment->media_start), media_time,
8114           GST_TIME_ARGS (segment->media_stop),
8115           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8116           stream->timescale);
8117       if (segment->stop_time > qtdemux->segment.stop) {
8118         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8119             " extends to %" GST_TIME_FORMAT
8120             " past the end of the file duration %" GST_TIME_FORMAT
8121             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8122             GST_TIME_ARGS (qtdemux->segment.stop));
8123         qtdemux->segment.stop = segment->stop_time;
8124       }
8125     }
8126     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8127     stream->n_segments = count;
8128     if (media_segments_count != 1)
8129       allow_pushbased_edts = FALSE;
8130   }
8131 done:
8132
8133   /* push based does not handle segments, so act accordingly here,
8134    * and warn if applicable */
8135   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8136     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8137     /* remove and use default one below, we stream like it anyway */
8138     g_free (stream->segments);
8139     stream->segments = NULL;
8140     stream->n_segments = 0;
8141   }
8142
8143   /* no segments, create one to play the complete trak */
8144   if (stream->n_segments == 0) {
8145     GstClockTime stream_duration =
8146         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8147
8148     if (stream->segments == NULL)
8149       stream->segments = g_new (QtDemuxSegment, 1);
8150
8151     /* represent unknown our way */
8152     if (stream_duration == 0)
8153       stream_duration = GST_CLOCK_TIME_NONE;
8154
8155     stream->segments[0].time = 0;
8156     stream->segments[0].stop_time = stream_duration;
8157     stream->segments[0].duration = stream_duration;
8158     stream->segments[0].media_start = 0;
8159     stream->segments[0].media_stop = stream_duration;
8160     stream->segments[0].rate = 1.0;
8161     stream->segments[0].trak_media_start = 0;
8162
8163     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8164         GST_TIME_ARGS (stream_duration));
8165     stream->n_segments = 1;
8166     stream->dummy_segment = TRUE;
8167   }
8168   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8169
8170   return TRUE;
8171 }
8172
8173 /*
8174  * Parses the stsd atom of a svq3 trak looking for
8175  * the SMI and gama atoms.
8176  */
8177 static void
8178 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8179     guint8 ** gamma, GstBuffer ** seqh)
8180 {
8181   guint8 *_gamma = NULL;
8182   GstBuffer *_seqh = NULL;
8183   guint8 *stsd_data = stsd->data;
8184   guint32 length = QT_UINT32 (stsd_data);
8185   guint16 version;
8186
8187   if (length < 32) {
8188     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8189     goto end;
8190   }
8191
8192   stsd_data += 32;
8193   length -= 32;
8194   version = QT_UINT16 (stsd_data);
8195   if (version == 3) {
8196     if (length >= 70) {
8197       length -= 70;
8198       stsd_data += 70;
8199       while (length > 8) {
8200         guint32 fourcc, size;
8201         guint8 *data;
8202         size = QT_UINT32 (stsd_data);
8203         fourcc = QT_FOURCC (stsd_data + 4);
8204         data = stsd_data + 8;
8205
8206         if (size == 0) {
8207           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8208               "svq3 atom parsing");
8209           goto end;
8210         }
8211
8212         switch (fourcc) {
8213           case FOURCC_gama:{
8214             if (size == 12) {
8215               _gamma = data;
8216             } else {
8217               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8218                   " for gama atom, expected 12", size);
8219             }
8220             break;
8221           }
8222           case FOURCC_SMI_:{
8223             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8224               guint32 seqh_size;
8225               if (_seqh != NULL) {
8226                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8227                     " found, ignoring");
8228               } else {
8229                 seqh_size = QT_UINT32 (data + 4);
8230                 if (seqh_size > 0) {
8231                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8232                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8233                 }
8234               }
8235             }
8236             break;
8237           }
8238           default:{
8239             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8240                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8241           }
8242         }
8243
8244         if (size <= length) {
8245           length -= size;
8246           stsd_data += size;
8247         }
8248       }
8249     } else {
8250       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8251     }
8252   } else {
8253     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8254         G_GUINT16_FORMAT, version);
8255     goto end;
8256   }
8257
8258 end:
8259   if (gamma) {
8260     *gamma = _gamma;
8261   }
8262   if (seqh) {
8263     *seqh = _seqh;
8264   } else if (_seqh) {
8265     gst_buffer_unref (_seqh);
8266   }
8267 }
8268
8269 static gchar *
8270 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8271 {
8272   GNode *dinf;
8273   GstByteReader dref;
8274   gchar *uri = NULL;
8275
8276   /*
8277    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8278    * atom that might contain a 'data' atom with the rtsp uri.
8279    * This case was reported in bug #597497, some info about
8280    * the hndl atom can be found in TN1195
8281    */
8282   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8283   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8284
8285   if (dinf) {
8286     guint32 dref_num_entries = 0;
8287     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8288         gst_byte_reader_skip (&dref, 4) &&
8289         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8290       gint i;
8291
8292       /* search dref entries for hndl atom */
8293       for (i = 0; i < dref_num_entries; i++) {
8294         guint32 size = 0, type;
8295         guint8 string_len = 0;
8296         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8297             qt_atom_parser_get_fourcc (&dref, &type)) {
8298           if (type == FOURCC_hndl) {
8299             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8300
8301             /* skip data reference handle bytes and the
8302              * following pascal string and some extra 4
8303              * bytes I have no idea what are */
8304             if (!gst_byte_reader_skip (&dref, 4) ||
8305                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8306                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8307               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8308               break;
8309             }
8310
8311             /* iterate over the atoms to find the data atom */
8312             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8313               guint32 atom_size;
8314               guint32 atom_type;
8315
8316               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8317                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8318                 if (atom_type == FOURCC_data) {
8319                   const guint8 *uri_aux = NULL;
8320
8321                   /* found the data atom that might contain the rtsp uri */
8322                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8323                       "hndl atom, interpreting it as an URI");
8324                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8325                           &uri_aux)) {
8326                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8327                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8328                     else
8329                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8330                           "didn't contain a rtsp address");
8331                   } else {
8332                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8333                         "atom contents");
8334                   }
8335                   break;
8336                 }
8337                 /* skipping to the next entry */
8338                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8339                   break;
8340               } else {
8341                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8342                     "atom header");
8343                 break;
8344               }
8345             }
8346             break;
8347           }
8348           /* skip to the next entry */
8349           if (!gst_byte_reader_skip (&dref, size - 8))
8350             break;
8351         } else {
8352           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8353         }
8354       }
8355       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8356     }
8357   }
8358   return uri;
8359 }
8360
8361 #define AMR_NB_ALL_MODES        0x81ff
8362 #define AMR_WB_ALL_MODES        0x83ff
8363 static guint
8364 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8365 {
8366   /* The 'damr' atom is of the form:
8367    *
8368    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8369    *    32 b       8 b          16 b           8 b                 8 b
8370    *
8371    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8372    * represents the highest mode used in the stream (and thus the maximum
8373    * bitrate), with a couple of special cases as seen below.
8374    */
8375
8376   /* Map of frame type ID -> bitrate */
8377   static const guint nb_bitrates[] = {
8378     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8379   };
8380   static const guint wb_bitrates[] = {
8381     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8382   };
8383   GstMapInfo map;
8384   gsize max_mode;
8385   guint16 mode_set;
8386
8387   gst_buffer_map (buf, &map, GST_MAP_READ);
8388
8389   if (map.size != 0x11) {
8390     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8391     goto bad_data;
8392   }
8393
8394   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
8395     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8396         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8397     goto bad_data;
8398   }
8399
8400   mode_set = QT_UINT16 (map.data + 13);
8401
8402   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8403     max_mode = 7 + (wb ? 1 : 0);
8404   else
8405     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8406     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8407
8408   if (max_mode == -1) {
8409     GST_DEBUG ("No mode indication was found (mode set) = %x",
8410         (guint) mode_set);
8411     goto bad_data;
8412   }
8413
8414   gst_buffer_unmap (buf, &map);
8415   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8416
8417 bad_data:
8418   gst_buffer_unmap (buf, &map);
8419   return 0;
8420 }
8421
8422 static gboolean
8423 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8424     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8425 {
8426   /*
8427    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8428    * [0 1 2]
8429    * [3 4 5]
8430    * [6 7 8]
8431    */
8432
8433   if (gst_byte_reader_get_remaining (reader) < 36)
8434     return FALSE;
8435
8436   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8437   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8438   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8439   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8440   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8441   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8442   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8443   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8444   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8445
8446   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8447   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8448       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8449       matrix[2] & 0xFF);
8450   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8451       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8452       matrix[5] & 0xFF);
8453   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8454       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8455       matrix[8] & 0xFF);
8456
8457   return TRUE;
8458 }
8459
8460 static void
8461 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8462     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8463 {
8464
8465 /* [a b c]
8466  * [d e f]
8467  * [g h i]
8468  *
8469  * This macro will only compare value abdegh, it expects cfi to have already
8470  * been checked
8471  */
8472 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8473                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8474
8475   /* only handle the cases where the last column has standard values */
8476   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8477     const gchar *rotation_tag = NULL;
8478
8479     /* no rotation needed */
8480     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8481       /* NOP */
8482     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8483       rotation_tag = "rotate-90";
8484     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8485       rotation_tag = "rotate-180";
8486     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8487       rotation_tag = "rotate-270";
8488     } else {
8489       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8490     }
8491
8492     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8493         rotation_tag);
8494     if (rotation_tag != NULL) {
8495       if (*taglist == NULL)
8496         *taglist = gst_tag_list_new_empty ();
8497       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8498           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8499     }
8500   } else {
8501     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8502   }
8503 }
8504
8505 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8506  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8507  * Common Encryption (cenc), the function will also parse the tenc box (defined
8508  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8509  * (typically an enc[v|a|t|s] sample entry); the function will set
8510  * @original_fmt to the fourcc of the original unencrypted stream format.
8511  * Returns TRUE if successful; FALSE otherwise. */
8512 static gboolean
8513 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8514     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8515 {
8516   GNode *sinf;
8517   GNode *frma;
8518   GNode *schm;
8519   GNode *schi;
8520
8521   g_return_val_if_fail (qtdemux != NULL, FALSE);
8522   g_return_val_if_fail (stream != NULL, FALSE);
8523   g_return_val_if_fail (container != NULL, FALSE);
8524   g_return_val_if_fail (original_fmt != NULL, FALSE);
8525
8526   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8527   if (G_UNLIKELY (!sinf)) {
8528     if (stream->protection_scheme_type == FOURCC_cenc) {
8529       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8530           "mandatory for Common Encryption");
8531       return FALSE;
8532     }
8533     return TRUE;
8534   }
8535
8536   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8537   if (G_UNLIKELY (!frma)) {
8538     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8539     return FALSE;
8540   }
8541
8542   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8543   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8544       GST_FOURCC_ARGS (*original_fmt));
8545
8546   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8547   if (!schm) {
8548     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8549     return FALSE;
8550   }
8551   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8552   stream->protection_scheme_version =
8553       QT_UINT32 ((const guint8 *) schm->data + 16);
8554
8555   GST_DEBUG_OBJECT (qtdemux,
8556       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8557       "protection_scheme_version: %#010x",
8558       GST_FOURCC_ARGS (stream->protection_scheme_type),
8559       stream->protection_scheme_version);
8560
8561   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8562   if (!schi) {
8563     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8564     return FALSE;
8565   }
8566   if (stream->protection_scheme_type == FOURCC_cenc) {
8567     QtDemuxCencSampleSetInfo *info;
8568     GNode *tenc;
8569     const guint8 *tenc_data;
8570     guint32 isEncrypted;
8571     guint8 iv_size;
8572     const guint8 *default_kid;
8573     GstBuffer *kid_buf;
8574
8575     if (G_UNLIKELY (!stream->protection_scheme_info))
8576       stream->protection_scheme_info =
8577           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8578
8579     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
8580
8581     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
8582     if (!tenc) {
8583       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
8584           "which is mandatory for Common Encryption");
8585       return FALSE;
8586     }
8587     tenc_data = (const guint8 *) tenc->data + 12;
8588     isEncrypted = QT_UINT24 (tenc_data);
8589     iv_size = QT_UINT8 (tenc_data + 3);
8590     default_kid = (tenc_data + 4);
8591     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
8592     gst_buffer_fill (kid_buf, 0, default_kid, 16);
8593     if (info->default_properties)
8594       gst_structure_free (info->default_properties);
8595     info->default_properties =
8596         gst_structure_new ("application/x-cenc",
8597         "iv_size", G_TYPE_UINT, iv_size,
8598         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
8599         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
8600     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
8601         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
8602     gst_buffer_unref (kid_buf);
8603   }
8604   return TRUE;
8605 }
8606
8607 /* parse the traks.
8608  * With each track we associate a new QtDemuxStream that contains all the info
8609  * about the trak.
8610  * traks that do not decode to something (like strm traks) will not have a pad.
8611  */
8612 static gboolean
8613 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
8614 {
8615   GstByteReader tkhd;
8616   int offset;
8617   GNode *mdia;
8618   GNode *mdhd;
8619   GNode *hdlr;
8620   GNode *minf;
8621   GNode *stbl;
8622   GNode *stsd;
8623   GNode *mp4a;
8624   GNode *mp4v;
8625   GNode *wave;
8626   GNode *esds;
8627   GNode *pasp;
8628   GNode *tref;
8629   GNode *udta;
8630   GNode *svmi;
8631
8632   QtDemuxStream *stream = NULL;
8633   gboolean new_stream = FALSE;
8634   gchar *codec = NULL;
8635   const guint8 *stsd_data;
8636   guint16 lang_code;            /* quicktime lang code or packed iso code */
8637   guint32 version;
8638   guint32 tkhd_flags = 0;
8639   guint8 tkhd_version = 0;
8640   guint32 fourcc;
8641   guint value_size, stsd_len, len;
8642   guint32 track_id;
8643   guint32 dummy;
8644
8645   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
8646
8647   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
8648       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
8649       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
8650     goto corrupt_file;
8651
8652   /* pick between 64 or 32 bits */
8653   value_size = tkhd_version == 1 ? 8 : 4;
8654   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
8655       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
8656     goto corrupt_file;
8657
8658   if (!qtdemux->got_moov) {
8659     if (qtdemux_find_stream (qtdemux, track_id))
8660       goto existing_stream;
8661     stream = _create_stream ();
8662     stream->track_id = track_id;
8663     new_stream = TRUE;
8664   } else {
8665     stream = qtdemux_find_stream (qtdemux, track_id);
8666     if (!stream) {
8667       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
8668       goto skip_track;
8669     }
8670
8671     /* flush samples data from this track from previous moov */
8672     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
8673     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
8674   }
8675   /* need defaults for fragments */
8676   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
8677
8678   if (stream->pending_tags == NULL)
8679     stream->pending_tags = gst_tag_list_new_empty ();
8680
8681   if ((tkhd_flags & 1) == 0)
8682     stream->disabled = TRUE;
8683
8684   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
8685       tkhd_version, tkhd_flags, stream->track_id);
8686
8687   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
8688     goto corrupt_file;
8689
8690   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
8691     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
8692     if (qtdemux->major_brand != FOURCC_mjp2 ||
8693         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
8694       goto corrupt_file;
8695   }
8696
8697   len = QT_UINT32 ((guint8 *) mdhd->data);
8698   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
8699   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
8700   if (version == 0x01000000) {
8701     if (len < 38)
8702       goto corrupt_file;
8703     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
8704     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
8705     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
8706   } else {
8707     if (len < 30)
8708       goto corrupt_file;
8709     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
8710     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
8711     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
8712   }
8713
8714   if (lang_code < 0x400) {
8715     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
8716   } else if (lang_code == 0x7fff) {
8717     stream->lang_id[0] = 0;     /* unspecified */
8718   } else {
8719     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
8720     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
8721     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
8722     stream->lang_id[3] = 0;
8723   }
8724
8725   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
8726       stream->timescale);
8727   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
8728       stream->duration);
8729   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
8730       lang_code, stream->lang_id);
8731
8732   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
8733     goto corrupt_file;
8734
8735   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
8736     /* chapters track reference */
8737     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
8738     if (chap) {
8739       gsize length = GST_READ_UINT32_BE (chap->data);
8740       if (qtdemux->chapters_track_id)
8741         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
8742
8743       if (length >= 12) {
8744         qtdemux->chapters_track_id =
8745             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
8746       }
8747     }
8748   }
8749
8750   /* fragmented files may have bogus duration in moov */
8751   if (!qtdemux->fragmented &&
8752       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
8753     guint64 tdur1, tdur2;
8754
8755     /* don't overflow */
8756     tdur1 = stream->timescale * (guint64) qtdemux->duration;
8757     tdur2 = qtdemux->timescale * (guint64) stream->duration;
8758
8759     /* HACK:
8760      * some of those trailers, nowadays, have prologue images that are
8761      * themselves vide tracks as well. I haven't really found a way to
8762      * identify those yet, except for just looking at their duration. */
8763     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
8764       GST_WARNING_OBJECT (qtdemux,
8765           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
8766           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
8767           "found, assuming preview image or something; skipping track",
8768           stream->duration, stream->timescale, qtdemux->duration,
8769           qtdemux->timescale);
8770       if (new_stream)
8771         gst_qtdemux_stream_free (qtdemux, stream);
8772       return TRUE;
8773     }
8774   }
8775
8776   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
8777     goto corrupt_file;
8778
8779   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
8780       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
8781
8782   len = QT_UINT32 ((guint8 *) hdlr->data);
8783   if (len >= 20)
8784     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
8785   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
8786       GST_FOURCC_ARGS (stream->subtype));
8787
8788   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
8789     goto corrupt_file;
8790
8791   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
8792     goto corrupt_file;
8793
8794   /*parse svmi header if existing */
8795   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
8796   if (svmi) {
8797     len = QT_UINT32 ((guint8 *) svmi->data);
8798     version = QT_UINT32 ((guint8 *) svmi->data + 8);
8799     if (!version) {
8800       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
8801       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
8802       guint8 frame_type, frame_layout;
8803
8804       /* MPEG-A stereo video */
8805       if (qtdemux->major_brand == FOURCC_ss02)
8806         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
8807
8808       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
8809       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
8810       switch (frame_type) {
8811         case 0:
8812           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
8813           break;
8814         case 1:
8815           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
8816           break;
8817         case 2:
8818           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
8819           break;
8820         case 3:
8821           /* mode 3 is primary/secondary view sequence, ie
8822            * left/right views in separate tracks. See section 7.2
8823            * of ISO/IEC 23000-11:2009 */
8824           GST_FIXME_OBJECT (qtdemux,
8825               "Implement stereo video in separate streams");
8826       }
8827
8828       if ((frame_layout & 0x1) == 0)
8829         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
8830
8831       GST_LOG_OBJECT (qtdemux,
8832           "StereoVideo: composition type: %u, is_left_first: %u",
8833           frame_type, frame_layout);
8834       stream->multiview_mode = mode;
8835       stream->multiview_flags = flags;
8836     }
8837   }
8838
8839   /* parse stsd */
8840   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
8841     goto corrupt_file;
8842   stsd_data = (const guint8 *) stsd->data;
8843
8844   /* stsd should at least have one entry */
8845   stsd_len = QT_UINT32 (stsd_data);
8846   if (stsd_len < 24) {
8847     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
8848     if (stream->subtype == FOURCC_vivo) {
8849       if (new_stream)
8850         gst_qtdemux_stream_free (qtdemux, stream);
8851       return TRUE;
8852     } else {
8853       goto corrupt_file;
8854     }
8855   }
8856
8857   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
8858
8859   /* and that entry should fit within stsd */
8860   len = QT_UINT32 (stsd_data + 16);
8861   if (len > stsd_len + 16)
8862     goto corrupt_file;
8863
8864   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
8865   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
8866       GST_FOURCC_ARGS (stream->fourcc));
8867   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
8868
8869   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
8870     goto error_encrypted;
8871
8872   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
8873     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
8874     stream->protected = TRUE;
8875     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
8876       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
8877   }
8878
8879   if (stream->subtype == FOURCC_vide) {
8880     guint32 w = 0, h = 0;
8881     gboolean gray;
8882     gint depth, palette_size, palette_count;
8883     guint32 matrix[9];
8884     guint32 *palette_data = NULL;
8885
8886     stream->sampled = TRUE;
8887
8888     /* version 1 uses some 64-bit ints */
8889     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
8890       goto corrupt_file;
8891
8892     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
8893       goto corrupt_file;
8894
8895     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
8896         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
8897       goto corrupt_file;
8898
8899     stream->display_width = w >> 16;
8900     stream->display_height = h >> 16;
8901
8902     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
8903         &stream->pending_tags);
8904
8905     offset = 16;
8906     if (len < 86)
8907       goto corrupt_file;
8908
8909     stream->width = QT_UINT16 (stsd_data + offset + 32);
8910     stream->height = QT_UINT16 (stsd_data + offset + 34);
8911     stream->fps_n = 0;          /* this is filled in later */
8912     stream->fps_d = 0;          /* this is filled in later */
8913     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
8914     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
8915
8916     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
8917         stream->width, stream->height, stream->bits_per_sample,
8918         stream->color_table_id);
8919
8920     depth = stream->bits_per_sample;
8921
8922     /* more than 32 bits means grayscale */
8923     gray = (depth > 32);
8924     /* low 32 bits specify the depth  */
8925     depth &= 0x1F;
8926
8927     /* different number of palette entries is determined by depth. */
8928     palette_count = 0;
8929     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
8930       palette_count = (1 << depth);
8931     palette_size = palette_count * 4;
8932
8933     if (stream->color_table_id) {
8934       switch (palette_count) {
8935         case 0:
8936           break;
8937         case 2:
8938           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
8939           break;
8940         case 4:
8941           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
8942           break;
8943         case 16:
8944           if (gray)
8945             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
8946           else
8947             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
8948           break;
8949         case 256:
8950           if (gray)
8951             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
8952           else
8953             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
8954           break;
8955         default:
8956           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8957               (_("The video in this file might not play correctly.")),
8958               ("unsupported palette depth %d", depth));
8959           break;
8960       }
8961     } else {
8962       gint i, j, start, end;
8963
8964       if (len < 94)
8965         goto corrupt_file;
8966
8967       /* read table */
8968       start = QT_UINT32 (stsd_data + offset + 86);
8969       palette_count = QT_UINT16 (stsd_data + offset + 90);
8970       end = QT_UINT16 (stsd_data + offset + 92);
8971
8972       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
8973           start, end, palette_count);
8974
8975       if (end > 255)
8976         end = 255;
8977       if (start > end)
8978         start = end;
8979
8980       if (len < 94 + (end - start) * 8)
8981         goto corrupt_file;
8982
8983       /* palette is always the same size */
8984       palette_data = g_malloc0 (256 * 4);
8985       palette_size = 256 * 4;
8986
8987       for (j = 0, i = start; i <= end; j++, i++) {
8988         guint32 a, r, g, b;
8989
8990         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
8991         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
8992         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
8993         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
8994
8995         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
8996             (g & 0xff00) | (b >> 8);
8997       }
8998     }
8999
9000     if (stream->caps)
9001       gst_caps_unref (stream->caps);
9002
9003     stream->caps =
9004         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9005     if (G_UNLIKELY (!stream->caps)) {
9006       g_free (palette_data);
9007       goto unknown_stream;
9008     }
9009
9010     if (codec) {
9011       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9012           GST_TAG_VIDEO_CODEC, codec, NULL);
9013       g_free (codec);
9014       codec = NULL;
9015     }
9016
9017
9018     if (palette_data) {
9019       GstStructure *s;
9020
9021       if (stream->rgb8_palette)
9022         gst_memory_unref (stream->rgb8_palette);
9023       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9024           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9025
9026       s = gst_caps_get_structure (stream->caps, 0);
9027
9028       /* non-raw video has a palette_data property. raw video has the palette as
9029        * an extra plane that we append to the output buffers before we push
9030        * them*/
9031       if (!gst_structure_has_name (s, "video/x-raw")) {
9032         GstBuffer *palette;
9033
9034         palette = gst_buffer_new ();
9035         gst_buffer_append_memory (palette, stream->rgb8_palette);
9036         stream->rgb8_palette = NULL;
9037
9038         gst_caps_set_simple (stream->caps, "palette_data",
9039             GST_TYPE_BUFFER, palette, NULL);
9040         gst_buffer_unref (palette);
9041       }
9042     } else if (palette_count != 0) {
9043       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9044           (NULL), ("Unsupported palette depth %d", depth));
9045     }
9046
9047     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9048         QT_UINT16 (stsd_data + offset + 48));
9049
9050     esds = NULL;
9051     pasp = NULL;
9052     /* pick 'the' stsd child */
9053     if (!stream->protected)
9054       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9055     else
9056       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9057
9058     if (mp4v) {
9059       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9060       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9061     }
9062
9063     if (pasp) {
9064       const guint8 *pasp_data = (const guint8 *) pasp->data;
9065
9066       stream->par_w = QT_UINT32 (pasp_data + 8);
9067       stream->par_h = QT_UINT32 (pasp_data + 12);
9068     } else {
9069       stream->par_w = 0;
9070       stream->par_h = 0;
9071     }
9072
9073     if (esds) {
9074       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9075     } else {
9076       switch (fourcc) {
9077         case FOURCC_H264:
9078         case FOURCC_avc1:
9079         case FOURCC_avc3:
9080         {
9081           gint len = QT_UINT32 (stsd_data) - 0x66;
9082           const guint8 *avc_data = stsd_data + 0x66;
9083
9084           /* find avcC */
9085           while (len >= 0x8) {
9086             gint size;
9087
9088             if (QT_UINT32 (avc_data) <= len)
9089               size = QT_UINT32 (avc_data) - 0x8;
9090             else
9091               size = len - 0x8;
9092
9093             if (size < 1)
9094               /* No real data, so break out */
9095               break;
9096
9097             switch (QT_FOURCC (avc_data + 0x4)) {
9098               case FOURCC_avcC:
9099               {
9100                 /* parse, if found */
9101                 GstBuffer *buf;
9102
9103                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9104
9105                 /* First 4 bytes are the length of the atom, the next 4 bytes
9106                  * are the fourcc, the next 1 byte is the version, and the
9107                  * subsequent bytes are profile_tier_level structure like data. */
9108                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9109                     avc_data + 8 + 1, size - 1);
9110                 buf = gst_buffer_new_and_alloc (size);
9111                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9112                 gst_caps_set_simple (stream->caps,
9113                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9114                 gst_buffer_unref (buf);
9115
9116                 break;
9117               }
9118               case FOURCC_strf:
9119               {
9120                 GstBuffer *buf;
9121
9122                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9123
9124                 /* First 4 bytes are the length of the atom, the next 4 bytes
9125                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9126                  * next 1 byte is the version, and the
9127                  * subsequent bytes are sequence parameter set like data. */
9128
9129                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9130                 if (size > 1) {
9131                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9132                       avc_data + 8 + 40 + 1, size - 1);
9133
9134                   buf = gst_buffer_new_and_alloc (size);
9135                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9136                   gst_caps_set_simple (stream->caps,
9137                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9138                   gst_buffer_unref (buf);
9139                 }
9140                 break;
9141               }
9142               case FOURCC_btrt:
9143               {
9144                 guint avg_bitrate, max_bitrate;
9145
9146                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9147                 if (size < 12)
9148                   break;
9149
9150                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9151                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9152
9153                 if (!max_bitrate && !avg_bitrate)
9154                   break;
9155
9156                 /* Some muxers seem to swap the average and maximum bitrates
9157                  * (I'm looking at you, YouTube), so we swap for sanity. */
9158                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9159                   guint temp = avg_bitrate;
9160
9161                   avg_bitrate = max_bitrate;
9162                   max_bitrate = temp;
9163                 }
9164
9165                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9166                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9167                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
9168                 }
9169                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
9170                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9171                       GST_TAG_BITRATE, avg_bitrate, NULL);
9172                 }
9173
9174                 break;
9175               }
9176
9177               default:
9178                 break;
9179             }
9180
9181             len -= size + 8;
9182             avc_data += size + 8;
9183           }
9184
9185           break;
9186         }
9187         case FOURCC_H265:
9188         case FOURCC_hvc1:
9189         case FOURCC_hev1:
9190         {
9191           gint len = QT_UINT32 (stsd_data) - 0x66;
9192           const guint8 *hevc_data = stsd_data + 0x66;
9193
9194           /* find hevc */
9195           while (len >= 0x8) {
9196             gint size;
9197
9198             if (QT_UINT32 (hevc_data) <= len)
9199               size = QT_UINT32 (hevc_data) - 0x8;
9200             else
9201               size = len - 0x8;
9202
9203             if (size < 1)
9204               /* No real data, so break out */
9205               break;
9206
9207             switch (QT_FOURCC (hevc_data + 0x4)) {
9208               case FOURCC_hvcC:
9209               {
9210                 /* parse, if found */
9211                 GstBuffer *buf;
9212
9213                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9214
9215                 /* First 4 bytes are the length of the atom, the next 4 bytes
9216                  * are the fourcc, the next 1 byte is the version, and the
9217                  * subsequent bytes are sequence parameter set like data. */
9218                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9219                     (stream->caps, hevc_data + 8 + 1, size - 1);
9220
9221                 buf = gst_buffer_new_and_alloc (size);
9222                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9223                 gst_caps_set_simple (stream->caps,
9224                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9225                 gst_buffer_unref (buf);
9226                 break;
9227               }
9228               default:
9229                 break;
9230             }
9231             len -= size + 8;
9232             hevc_data += size + 8;
9233           }
9234           break;
9235         }
9236         case FOURCC_mp4v:
9237         case FOURCC_MP4V:
9238         case FOURCC_fmp4:
9239         case FOURCC_FMP4:
9240         {
9241           GNode *glbl;
9242
9243           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9244               GST_FOURCC_ARGS (fourcc));
9245
9246           /* codec data might be in glbl extension atom */
9247           glbl = mp4v ?
9248               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9249           if (glbl) {
9250             guint8 *data;
9251             GstBuffer *buf;
9252             gint len;
9253
9254             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9255             data = glbl->data;
9256             len = QT_UINT32 (data);
9257             if (len > 0x8) {
9258               len -= 0x8;
9259               buf = gst_buffer_new_and_alloc (len);
9260               gst_buffer_fill (buf, 0, data + 8, len);
9261               gst_caps_set_simple (stream->caps,
9262                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9263               gst_buffer_unref (buf);
9264             }
9265           }
9266           break;
9267         }
9268         case FOURCC_mjp2:
9269         {
9270           /* see annex I of the jpeg2000 spec */
9271           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9272           const guint8 *data;
9273           const gchar *colorspace = NULL;
9274           gint ncomp = 0;
9275           guint32 ncomp_map = 0;
9276           gint32 *comp_map = NULL;
9277           guint32 nchan_def = 0;
9278           gint32 *chan_def = NULL;
9279
9280           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9281           /* some required atoms */
9282           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9283           if (!mjp2)
9284             break;
9285           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9286           if (!jp2h)
9287             break;
9288
9289           /* number of components; redundant with info in codestream, but useful
9290              to a muxer */
9291           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9292           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9293             break;
9294           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9295
9296           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9297           if (!colr)
9298             break;
9299           GST_DEBUG_OBJECT (qtdemux, "found colr");
9300           /* extract colour space info */
9301           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9302             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9303               case 16:
9304                 colorspace = "sRGB";
9305                 break;
9306               case 17:
9307                 colorspace = "GRAY";
9308                 break;
9309               case 18:
9310                 colorspace = "sYUV";
9311                 break;
9312               default:
9313                 colorspace = NULL;
9314                 break;
9315             }
9316           }
9317           if (!colorspace)
9318             /* colr is required, and only values 16, 17, and 18 are specified,
9319                so error if we have no colorspace */
9320             break;
9321
9322           /* extract component mapping */
9323           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9324           if (cmap) {
9325             guint32 cmap_len = 0;
9326             int i;
9327             cmap_len = QT_UINT32 (cmap->data);
9328             if (cmap_len >= 8) {
9329               /* normal box, subtract off header */
9330               cmap_len -= 8;
9331               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9332               if (cmap_len % 4 == 0) {
9333                 ncomp_map = (cmap_len / 4);
9334                 comp_map = g_new0 (gint32, ncomp_map);
9335                 for (i = 0; i < ncomp_map; i++) {
9336                   guint16 cmp;
9337                   guint8 mtyp, pcol;
9338                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9339                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9340                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9341                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9342                 }
9343               }
9344             }
9345           }
9346           /* extract channel definitions */
9347           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9348           if (cdef) {
9349             guint32 cdef_len = 0;
9350             int i;
9351             cdef_len = QT_UINT32 (cdef->data);
9352             if (cdef_len >= 10) {
9353               /* normal box, subtract off header and len */
9354               cdef_len -= 10;
9355               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9356               if (cdef_len % 6 == 0) {
9357                 nchan_def = (cdef_len / 6);
9358                 chan_def = g_new0 (gint32, nchan_def);
9359                 for (i = 0; i < nchan_def; i++)
9360                   chan_def[i] = -1;
9361                 for (i = 0; i < nchan_def; i++) {
9362                   guint16 cn, typ, asoc;
9363                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9364                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9365                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9366                   if (cn < nchan_def) {
9367                     switch (typ) {
9368                       case 0:
9369                         chan_def[cn] = asoc;
9370                         break;
9371                       case 1:
9372                         chan_def[cn] = 0;       /* alpha */
9373                         break;
9374                       default:
9375                         chan_def[cn] = -typ;
9376                     }
9377                   }
9378                 }
9379               }
9380             }
9381           }
9382
9383           gst_caps_set_simple (stream->caps,
9384               "num-components", G_TYPE_INT, ncomp, NULL);
9385           gst_caps_set_simple (stream->caps,
9386               "colorspace", G_TYPE_STRING, colorspace, NULL);
9387
9388           if (comp_map) {
9389             GValue arr = { 0, };
9390             GValue elt = { 0, };
9391             int i;
9392             g_value_init (&arr, GST_TYPE_ARRAY);
9393             g_value_init (&elt, G_TYPE_INT);
9394             for (i = 0; i < ncomp_map; i++) {
9395               g_value_set_int (&elt, comp_map[i]);
9396               gst_value_array_append_value (&arr, &elt);
9397             }
9398             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9399                 "component-map", &arr);
9400             g_value_unset (&elt);
9401             g_value_unset (&arr);
9402             g_free (comp_map);
9403           }
9404
9405           if (chan_def) {
9406             GValue arr = { 0, };
9407             GValue elt = { 0, };
9408             int i;
9409             g_value_init (&arr, GST_TYPE_ARRAY);
9410             g_value_init (&elt, G_TYPE_INT);
9411             for (i = 0; i < nchan_def; i++) {
9412               g_value_set_int (&elt, chan_def[i]);
9413               gst_value_array_append_value (&arr, &elt);
9414             }
9415             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9416                 "channel-definitions", &arr);
9417             g_value_unset (&elt);
9418             g_value_unset (&arr);
9419             g_free (chan_def);
9420           }
9421
9422           /* some optional atoms */
9423           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9424           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9425
9426           /* indicate possible fields in caps */
9427           if (field) {
9428             data = (guint8 *) field->data + 8;
9429             if (*data != 1)
9430               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9431                   (gint) * data, NULL);
9432           }
9433           /* add codec_data if provided */
9434           if (prefix) {
9435             GstBuffer *buf;
9436             gint len;
9437
9438             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9439             data = prefix->data;
9440             len = QT_UINT32 (data);
9441             if (len > 0x8) {
9442               len -= 0x8;
9443               buf = gst_buffer_new_and_alloc (len);
9444               gst_buffer_fill (buf, 0, data + 8, len);
9445               gst_caps_set_simple (stream->caps,
9446                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9447               gst_buffer_unref (buf);
9448             }
9449           }
9450           break;
9451         }
9452         case FOURCC_SVQ3:
9453         case FOURCC_VP31:
9454         {
9455           GstBuffer *buf;
9456           GstBuffer *seqh = NULL;
9457           guint8 *gamma_data = NULL;
9458           gint len = QT_UINT32 (stsd_data);
9459
9460           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9461           if (gamma_data) {
9462             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9463                 QT_FP32 (gamma_data), NULL);
9464           }
9465           if (seqh) {
9466             /* sorry for the bad name, but we don't know what this is, other
9467              * than its own fourcc */
9468             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9469                 NULL);
9470           }
9471
9472           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9473           buf = gst_buffer_new_and_alloc (len);
9474           gst_buffer_fill (buf, 0, stsd_data, len);
9475           gst_caps_set_simple (stream->caps,
9476               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9477           gst_buffer_unref (buf);
9478           break;
9479         }
9480         case FOURCC_rle_:
9481         case FOURCC_WRLE:
9482         {
9483           gst_caps_set_simple (stream->caps,
9484               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9485           break;
9486         }
9487         case FOURCC_XiTh:
9488         {
9489           GNode *xith, *xdxt;
9490
9491           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9492           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9493           if (!xith)
9494             break;
9495
9496           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9497           if (!xdxt)
9498             break;
9499
9500           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9501           /* collect the headers and store them in a stream list so that we can
9502            * send them out first */
9503           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9504           break;
9505         }
9506         case FOURCC_ovc1:
9507         {
9508           GNode *ovc1;
9509           guint8 *ovc1_data;
9510           guint ovc1_len;
9511           GstBuffer *buf;
9512
9513           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9514           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9515           if (!ovc1)
9516             break;
9517           ovc1_data = ovc1->data;
9518           ovc1_len = QT_UINT32 (ovc1_data);
9519           if (ovc1_len <= 198) {
9520             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9521             break;
9522           }
9523           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9524           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9525           gst_caps_set_simple (stream->caps,
9526               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9527           gst_buffer_unref (buf);
9528           break;
9529         }
9530         case FOURCC_vc_1:
9531         {
9532           gint len = QT_UINT32 (stsd_data) - 0x66;
9533           const guint8 *vc1_data = stsd_data + 0x66;
9534
9535           /* find dvc1 */
9536           while (len >= 8) {
9537             gint size;
9538
9539             if (QT_UINT32 (vc1_data) <= len)
9540               size = QT_UINT32 (vc1_data) - 8;
9541             else
9542               size = len - 8;
9543
9544             if (size < 1)
9545               /* No real data, so break out */
9546               break;
9547
9548             switch (QT_FOURCC (vc1_data + 0x4)) {
9549               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9550               {
9551                 GstBuffer *buf;
9552
9553                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9554                 buf = gst_buffer_new_and_alloc (size);
9555                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9556                 gst_caps_set_simple (stream->caps,
9557                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9558                 gst_buffer_unref (buf);
9559                 break;
9560               }
9561               default:
9562                 break;
9563             }
9564             len -= size + 8;
9565             vc1_data += size + 8;
9566           }
9567           break;
9568         }
9569         default:
9570           break;
9571       }
9572     }
9573
9574     GST_INFO_OBJECT (qtdemux,
9575         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9576         GST_FOURCC_ARGS (fourcc), stream->caps);
9577
9578   } else if (stream->subtype == FOURCC_soun) {
9579     int version, samplesize;
9580     guint16 compression_id;
9581     gboolean amrwb = FALSE;
9582
9583     offset = 32;
9584     /* sample description entry (16) + sound sample description v0 (20) */
9585     if (len < 36)
9586       goto corrupt_file;
9587
9588     version = QT_UINT32 (stsd_data + offset);
9589     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
9590     samplesize = QT_UINT16 (stsd_data + offset + 10);
9591     compression_id = QT_UINT16 (stsd_data + offset + 12);
9592     stream->rate = QT_FP32 (stsd_data + offset + 16);
9593
9594     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
9595     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
9596         QT_UINT32 (stsd_data + offset + 4));
9597     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
9598     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
9599     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
9600     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
9601         QT_UINT16 (stsd_data + offset + 14));
9602     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
9603
9604     if (compression_id == 0xfffe)
9605       stream->sampled = TRUE;
9606
9607     /* first assume uncompressed audio */
9608     stream->bytes_per_sample = samplesize / 8;
9609     stream->samples_per_frame = stream->n_channels;
9610     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
9611     stream->samples_per_packet = stream->samples_per_frame;
9612     stream->bytes_per_packet = stream->bytes_per_sample;
9613
9614     offset = 52;
9615     switch (fourcc) {
9616         /* Yes, these have to be hard-coded */
9617       case FOURCC_MAC6:
9618       {
9619         stream->samples_per_packet = 6;
9620         stream->bytes_per_packet = 1;
9621         stream->bytes_per_frame = 1 * stream->n_channels;
9622         stream->bytes_per_sample = 1;
9623         stream->samples_per_frame = 6 * stream->n_channels;
9624         break;
9625       }
9626       case FOURCC_MAC3:
9627       {
9628         stream->samples_per_packet = 3;
9629         stream->bytes_per_packet = 1;
9630         stream->bytes_per_frame = 1 * stream->n_channels;
9631         stream->bytes_per_sample = 1;
9632         stream->samples_per_frame = 3 * stream->n_channels;
9633         break;
9634       }
9635       case FOURCC_ima4:
9636       {
9637         stream->samples_per_packet = 64;
9638         stream->bytes_per_packet = 34;
9639         stream->bytes_per_frame = 34 * stream->n_channels;
9640         stream->bytes_per_sample = 2;
9641         stream->samples_per_frame = 64 * stream->n_channels;
9642         break;
9643       }
9644       case FOURCC_ulaw:
9645       case FOURCC_alaw:
9646       {
9647         stream->samples_per_packet = 1;
9648         stream->bytes_per_packet = 1;
9649         stream->bytes_per_frame = 1 * stream->n_channels;
9650         stream->bytes_per_sample = 1;
9651         stream->samples_per_frame = 1 * stream->n_channels;
9652         break;
9653       }
9654       case FOURCC_agsm:
9655       {
9656         stream->samples_per_packet = 160;
9657         stream->bytes_per_packet = 33;
9658         stream->bytes_per_frame = 33 * stream->n_channels;
9659         stream->bytes_per_sample = 2;
9660         stream->samples_per_frame = 160 * stream->n_channels;
9661         break;
9662       }
9663       default:
9664         break;
9665     }
9666
9667     if (version == 0x00010000) {
9668       /* sample description entry (16) + sound sample description v1 (20+16) */
9669       if (len < 52)
9670         goto corrupt_file;
9671
9672       switch (fourcc) {
9673         case FOURCC_twos:
9674         case FOURCC_sowt:
9675         case FOURCC_raw_:
9676           break;
9677         default:
9678         {
9679           /* only parse extra decoding config for non-pcm audio */
9680           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
9681           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
9682           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
9683           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
9684
9685           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
9686               stream->samples_per_packet);
9687           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
9688               stream->bytes_per_packet);
9689           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
9690               stream->bytes_per_frame);
9691           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
9692               stream->bytes_per_sample);
9693
9694           if (!stream->sampled && stream->bytes_per_packet) {
9695             stream->samples_per_frame = (stream->bytes_per_frame /
9696                 stream->bytes_per_packet) * stream->samples_per_packet;
9697             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
9698                 stream->samples_per_frame);
9699           }
9700           break;
9701         }
9702       }
9703     } else if (version == 0x00020000) {
9704       union
9705       {
9706         gdouble fp;
9707         guint64 val;
9708       } qtfp;
9709
9710       /* sample description entry (16) + sound sample description v2 (56) */
9711       if (len < 72)
9712         goto corrupt_file;
9713
9714       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
9715       stream->rate = qtfp.fp;
9716       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
9717
9718       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
9719       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
9720       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
9721       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
9722           QT_UINT32 (stsd_data + offset + 20));
9723       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
9724           QT_UINT32 (stsd_data + offset + 24));
9725       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
9726           QT_UINT32 (stsd_data + offset + 28));
9727       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
9728           QT_UINT32 (stsd_data + offset + 32));
9729     } else if (version != 0x00000) {
9730       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
9731     }
9732
9733     if (stream->caps)
9734       gst_caps_unref (stream->caps);
9735
9736     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
9737         stsd_data + 32, len - 16, &codec);
9738
9739     switch (fourcc) {
9740       case FOURCC_in24:
9741       {
9742         GNode *enda;
9743         GNode *in24;
9744
9745         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
9746
9747         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
9748         if (!enda) {
9749           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
9750           if (wave)
9751             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
9752         }
9753         if (enda) {
9754           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
9755           gst_caps_set_simple (stream->caps,
9756               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
9757         }
9758         break;
9759       }
9760       case FOURCC_owma:
9761       {
9762         GNode *owma;
9763         const guint8 *owma_data;
9764         const gchar *codec_name = NULL;
9765         guint owma_len;
9766         GstBuffer *buf;
9767         gint version = 1;
9768         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9769         /* FIXME this should also be gst_riff_strf_auds,
9770          * but the latter one is actually missing bits-per-sample :( */
9771         typedef struct
9772         {
9773           gint16 wFormatTag;
9774           gint16 nChannels;
9775           gint32 nSamplesPerSec;
9776           gint32 nAvgBytesPerSec;
9777           gint16 nBlockAlign;
9778           gint16 wBitsPerSample;
9779           gint16 cbSize;
9780         } WAVEFORMATEX;
9781         WAVEFORMATEX *wfex;
9782
9783         GST_DEBUG_OBJECT (qtdemux, "parse owma");
9784         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
9785         if (!owma)
9786           break;
9787         owma_data = owma->data;
9788         owma_len = QT_UINT32 (owma_data);
9789         if (owma_len <= 54) {
9790           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
9791           break;
9792         }
9793         wfex = (WAVEFORMATEX *) (owma_data + 36);
9794         buf = gst_buffer_new_and_alloc (owma_len - 54);
9795         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
9796         if (wfex->wFormatTag == 0x0161) {
9797           codec_name = "Windows Media Audio";
9798           version = 2;
9799         } else if (wfex->wFormatTag == 0x0162) {
9800           codec_name = "Windows Media Audio 9 Pro";
9801           version = 3;
9802         } else if (wfex->wFormatTag == 0x0163) {
9803           codec_name = "Windows Media Audio 9 Lossless";
9804           /* is that correct? gstffmpegcodecmap.c is missing it, but
9805            * fluendo codec seems to support it */
9806           version = 4;
9807         }
9808
9809         gst_caps_set_simple (stream->caps,
9810             "codec_data", GST_TYPE_BUFFER, buf,
9811             "wmaversion", G_TYPE_INT, version,
9812             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
9813             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
9814             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9815             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9816             NULL);
9817         gst_buffer_unref (buf);
9818
9819         if (codec_name) {
9820           g_free (codec);
9821           codec = g_strdup (codec_name);
9822         }
9823         break;
9824       }
9825       case FOURCC_wma_:
9826       {
9827         gint len = QT_UINT32 (stsd_data) - offset;
9828         const guint8 *wfex_data = stsd_data + offset;
9829         const gchar *codec_name = NULL;
9830         gint version = 1;
9831         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9832         /* FIXME this should also be gst_riff_strf_auds,
9833          * but the latter one is actually missing bits-per-sample :( */
9834         typedef struct
9835         {
9836           gint16 wFormatTag;
9837           gint16 nChannels;
9838           gint32 nSamplesPerSec;
9839           gint32 nAvgBytesPerSec;
9840           gint16 nBlockAlign;
9841           gint16 wBitsPerSample;
9842           gint16 cbSize;
9843         } WAVEFORMATEX;
9844         WAVEFORMATEX wfex;
9845
9846         /* FIXME: unify with similar wavformatex parsing code above */
9847         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
9848
9849         /* find wfex */
9850         while (len >= 8) {
9851           gint size;
9852
9853           if (QT_UINT32 (wfex_data) <= len)
9854             size = QT_UINT32 (wfex_data) - 8;
9855           else
9856             size = len - 8;
9857
9858           if (size < 1)
9859             /* No real data, so break out */
9860             break;
9861
9862           switch (QT_FOURCC (wfex_data + 4)) {
9863             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
9864             {
9865               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
9866
9867               if (size < 8 + 18)
9868                 break;
9869
9870               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
9871               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
9872               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
9873               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
9874               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
9875               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
9876               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
9877
9878               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
9879               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
9880                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
9881                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
9882                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
9883                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
9884
9885               if (wfex.wFormatTag == 0x0161) {
9886                 codec_name = "Windows Media Audio";
9887                 version = 2;
9888               } else if (wfex.wFormatTag == 0x0162) {
9889                 codec_name = "Windows Media Audio 9 Pro";
9890                 version = 3;
9891               } else if (wfex.wFormatTag == 0x0163) {
9892                 codec_name = "Windows Media Audio 9 Lossless";
9893                 /* is that correct? gstffmpegcodecmap.c is missing it, but
9894                  * fluendo codec seems to support it */
9895                 version = 4;
9896               }
9897
9898               gst_caps_set_simple (stream->caps,
9899                   "wmaversion", G_TYPE_INT, version,
9900                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
9901                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
9902                   "width", G_TYPE_INT, wfex.wBitsPerSample,
9903                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
9904
9905               if (size > wfex.cbSize) {
9906                 GstBuffer *buf;
9907
9908                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
9909                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
9910                     size - wfex.cbSize);
9911                 gst_caps_set_simple (stream->caps,
9912                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9913                 gst_buffer_unref (buf);
9914               } else {
9915                 GST_WARNING_OBJECT (qtdemux, "no codec data");
9916               }
9917
9918               if (codec_name) {
9919                 g_free (codec);
9920                 codec = g_strdup (codec_name);
9921               }
9922               break;
9923             }
9924             default:
9925               break;
9926           }
9927           len -= size + 8;
9928           wfex_data += size + 8;
9929         }
9930         break;
9931       }
9932       case FOURCC_opus:
9933       {
9934         GNode *opus;
9935         const guint8 *opus_data;
9936         guint8 *channel_mapping = NULL;
9937         guint32 rate;
9938         guint8 channels;
9939         guint8 channel_mapping_family;
9940         guint8 stream_count;
9941         guint8 coupled_count;
9942         guint8 i;
9943
9944         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
9945         opus_data = opus->data;
9946
9947         channels = GST_READ_UINT8 (opus_data + 45);
9948         rate = GST_READ_UINT32_LE (opus_data + 48);
9949         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
9950         stream_count = GST_READ_UINT8 (opus_data + 55);
9951         coupled_count = GST_READ_UINT8 (opus_data + 56);
9952
9953         if (channels > 0) {
9954           channel_mapping = g_malloc (channels * sizeof (guint8));
9955           for (i = 0; i < channels; i++)
9956             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
9957         }
9958
9959         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
9960             channel_mapping_family, stream_count, coupled_count,
9961             channel_mapping);
9962         break;
9963       }
9964       default:
9965         break;
9966     }
9967
9968     if (codec) {
9969       GstStructure *s;
9970       gint bitrate = 0;
9971
9972       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9973           GST_TAG_AUDIO_CODEC, codec, NULL);
9974       g_free (codec);
9975       codec = NULL;
9976
9977       /* some bitrate info may have ended up in caps */
9978       s = gst_caps_get_structure (stream->caps, 0);
9979       gst_structure_get_int (s, "bitrate", &bitrate);
9980       if (bitrate > 0)
9981         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9982             GST_TAG_BITRATE, bitrate, NULL);
9983     }
9984
9985     if (stream->protected && fourcc == FOURCC_mp4a)
9986       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
9987     else
9988       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
9989
9990     wave = NULL;
9991     esds = NULL;
9992     if (mp4a) {
9993       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
9994       if (wave)
9995         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
9996       if (!esds)
9997         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
9998     }
9999
10000
10001     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10002        16 bits is a byte-swapped wave-style codec identifier,
10003        and we can find a WAVE header internally to a 'wave' atom here.
10004        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10005        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10006        is big-endian).
10007      */
10008     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10009       if (len < offset + 20) {
10010         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10011       } else {
10012         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10013         const guint8 *data = stsd_data + offset + 16;
10014         GNode *wavenode;
10015         GNode *waveheadernode;
10016
10017         wavenode = g_node_new ((guint8 *) data);
10018         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10019           const guint8 *waveheader;
10020           guint32 headerlen;
10021
10022           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10023           if (waveheadernode) {
10024             waveheader = (const guint8 *) waveheadernode->data;
10025             headerlen = QT_UINT32 (waveheader);
10026
10027             if (headerlen > 8) {
10028               gst_riff_strf_auds *header = NULL;
10029               GstBuffer *headerbuf;
10030               GstBuffer *extra;
10031
10032               waveheader += 8;
10033               headerlen -= 8;
10034
10035               headerbuf = gst_buffer_new_and_alloc (headerlen);
10036               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10037
10038               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10039                       headerbuf, &header, &extra)) {
10040                 gst_caps_unref (stream->caps);
10041                 /* FIXME: Need to do something with the channel reorder map */
10042                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10043                     header, extra, NULL, NULL, NULL);
10044
10045                 if (extra)
10046                   gst_buffer_unref (extra);
10047                 g_free (header);
10048               }
10049             }
10050           } else
10051             GST_DEBUG ("Didn't find waveheadernode for this codec");
10052         }
10053         g_node_destroy (wavenode);
10054       }
10055     } else if (esds) {
10056       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10057     } else {
10058       switch (fourcc) {
10059 #if 0
10060           /* FIXME: what is in the chunk? */
10061         case FOURCC_QDMC:
10062         {
10063           gint len = QT_UINT32 (stsd_data);
10064
10065           /* seems to be always = 116 = 0x74 */
10066           break;
10067         }
10068 #endif
10069         case FOURCC_QDM2:
10070         {
10071           gint len = QT_UINT32 (stsd_data);
10072
10073           if (len > 0x4C) {
10074             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10075
10076             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10077             gst_caps_set_simple (stream->caps,
10078                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10079             gst_buffer_unref (buf);
10080           }
10081           gst_caps_set_simple (stream->caps,
10082               "samplesize", G_TYPE_INT, samplesize, NULL);
10083           break;
10084         }
10085         case FOURCC_alac:
10086         {
10087           GNode *alac, *wave = NULL;
10088
10089           /* apparently, m4a has this atom appended directly in the stsd entry,
10090            * while mov has it in a wave atom */
10091           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
10092           if (alac) {
10093             /* alac now refers to stsd entry atom */
10094             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
10095             if (wave)
10096               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
10097             else
10098               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
10099           }
10100           if (alac) {
10101             const guint8 *alac_data = alac->data;
10102             gint len = QT_UINT32 (alac->data);
10103             GstBuffer *buf;
10104
10105             if (len < 36) {
10106               GST_DEBUG_OBJECT (qtdemux,
10107                   "discarding alac atom with unexpected len %d", len);
10108             } else {
10109               /* codec-data contains alac atom size and prefix,
10110                * ffmpeg likes it that way, not quite gst-ish though ...*/
10111               buf = gst_buffer_new_and_alloc (len);
10112               gst_buffer_fill (buf, 0, alac->data, len);
10113               gst_caps_set_simple (stream->caps,
10114                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10115               gst_buffer_unref (buf);
10116
10117               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
10118               stream->n_channels = QT_UINT8 (alac_data + 21);
10119               stream->rate = QT_UINT32 (alac_data + 32);
10120             }
10121           }
10122           gst_caps_set_simple (stream->caps,
10123               "samplesize", G_TYPE_INT, samplesize, NULL);
10124           break;
10125         }
10126         case FOURCC_sawb:
10127           /* Fallthrough! */
10128           amrwb = TRUE;
10129         case FOURCC_samr:
10130         {
10131           gint len = QT_UINT32 (stsd_data);
10132
10133           if (len > 0x34) {
10134             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
10135             guint bitrate;
10136
10137             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
10138
10139             /* If we have enough data, let's try to get the 'damr' atom. See
10140              * the 3GPP container spec (26.244) for more details. */
10141             if ((len - 0x34) > 8 &&
10142                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
10143               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10144                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
10145             }
10146
10147             gst_caps_set_simple (stream->caps,
10148                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10149             gst_buffer_unref (buf);
10150           }
10151           break;
10152         }
10153         case FOURCC_mp4a:
10154         {
10155           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
10156           gint len = QT_UINT32 (stsd_data);
10157
10158           if (len >= 50) {
10159             guint16 sound_version = QT_UINT16 (stsd_data + 32);
10160
10161             if (sound_version == 1) {
10162               guint16 channels = QT_UINT16 (stsd_data + 40);
10163               guint32 time_scale = QT_UINT32 (stsd_data + 46);
10164               guint8 codec_data[2];
10165               GstBuffer *buf;
10166               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
10167
10168               gint sample_rate_index =
10169                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
10170
10171               /* build AAC codec data */
10172               codec_data[0] = profile << 3;
10173               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
10174               codec_data[1] = (sample_rate_index & 0x01) << 7;
10175               codec_data[1] |= (channels & 0xF) << 3;
10176
10177               buf = gst_buffer_new_and_alloc (2);
10178               gst_buffer_fill (buf, 0, codec_data, 2);
10179               gst_caps_set_simple (stream->caps,
10180                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10181               gst_buffer_unref (buf);
10182             }
10183           }
10184           break;
10185         }
10186         default:
10187           GST_INFO_OBJECT (qtdemux,
10188               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10189           break;
10190       }
10191     }
10192     GST_INFO_OBJECT (qtdemux,
10193         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10194         GST_FOURCC_ARGS (fourcc), stream->caps);
10195
10196   } else if (stream->subtype == FOURCC_strm) {
10197     if (fourcc == FOURCC_rtsp) {
10198       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
10199     } else {
10200       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
10201           GST_FOURCC_ARGS (fourcc));
10202       goto unknown_stream;
10203     }
10204     stream->sampled = TRUE;
10205   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
10206       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
10207
10208     stream->sampled = TRUE;
10209     stream->sparse = TRUE;
10210
10211     stream->caps =
10212         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10213     if (codec) {
10214       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10215           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10216       g_free (codec);
10217       codec = NULL;
10218     }
10219
10220     /* hunt for sort-of codec data */
10221     switch (fourcc) {
10222       case FOURCC_mp4s:
10223       {
10224         GNode *mp4s = NULL;
10225         GNode *esds = NULL;
10226
10227         /* look for palette in a stsd->mp4s->esds sub-atom */
10228         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10229         if (mp4s)
10230           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10231         if (esds == NULL) {
10232           /* Invalid STSD */
10233           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10234           break;
10235         }
10236
10237         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10238         break;
10239       }
10240       default:
10241         GST_INFO_OBJECT (qtdemux,
10242             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10243         break;
10244     }
10245     GST_INFO_OBJECT (qtdemux,
10246         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10247         GST_FOURCC_ARGS (fourcc), stream->caps);
10248   } else {
10249     /* everything in 1 sample */
10250     stream->sampled = TRUE;
10251
10252     stream->caps =
10253         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10254
10255     if (stream->caps == NULL)
10256       goto unknown_stream;
10257
10258     if (codec) {
10259       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10260           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10261       g_free (codec);
10262       codec = NULL;
10263     }
10264   }
10265
10266   /* promote to sampled format */
10267   if (stream->fourcc == FOURCC_samr) {
10268     /* force mono 8000 Hz for AMR */
10269     stream->sampled = TRUE;
10270     stream->n_channels = 1;
10271     stream->rate = 8000;
10272   } else if (stream->fourcc == FOURCC_sawb) {
10273     /* force mono 16000 Hz for AMR-WB */
10274     stream->sampled = TRUE;
10275     stream->n_channels = 1;
10276     stream->rate = 16000;
10277   } else if (stream->fourcc == FOURCC_mp4a) {
10278     stream->sampled = TRUE;
10279   }
10280
10281   /* collect sample information */
10282   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10283     goto samples_failed;
10284
10285   if (qtdemux->fragmented) {
10286     guint64 offset;
10287
10288     /* need all moov samples as basis; probably not many if any at all */
10289     /* prevent moof parsing taking of at this time */
10290     offset = qtdemux->moof_offset;
10291     qtdemux->moof_offset = 0;
10292     if (stream->n_samples &&
10293         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10294       qtdemux->moof_offset = offset;
10295       goto samples_failed;
10296     }
10297     qtdemux->moof_offset = 0;
10298     /* movie duration more reliable in this case (e.g. mehd) */
10299     if (qtdemux->segment.duration &&
10300         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10301       stream->duration =
10302           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10303   }
10304
10305   /* configure segments */
10306   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10307     goto segments_failed;
10308
10309   /* add some language tag, if useful */
10310   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10311       strcmp (stream->lang_id, "und")) {
10312     const gchar *lang_code;
10313
10314     /* convert ISO 639-2 code to ISO 639-1 */
10315     lang_code = gst_tag_get_language_code (stream->lang_id);
10316     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10317         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10318   }
10319
10320   /* Check for UDTA tags */
10321   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10322     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10323   }
10324
10325   /* now we are ready to add the stream */
10326   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10327     goto too_many_streams;
10328
10329   if (!qtdemux->got_moov) {
10330     qtdemux->streams[qtdemux->n_streams] = stream;
10331     qtdemux->n_streams++;
10332     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10333   }
10334
10335   return TRUE;
10336
10337 /* ERRORS */
10338 skip_track:
10339   {
10340     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10341     if (new_stream)
10342       gst_qtdemux_stream_free (qtdemux, stream);
10343     return TRUE;
10344   }
10345 corrupt_file:
10346   {
10347     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10348         (_("This file is corrupt and cannot be played.")), (NULL));
10349     if (new_stream)
10350       gst_qtdemux_stream_free (qtdemux, stream);
10351     return FALSE;
10352   }
10353 error_encrypted:
10354   {
10355     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10356     if (new_stream)
10357       gst_qtdemux_stream_free (qtdemux, stream);
10358     return FALSE;
10359   }
10360 samples_failed:
10361 segments_failed:
10362   {
10363     /* we posted an error already */
10364     /* free stbl sub-atoms */
10365     gst_qtdemux_stbl_free (stream);
10366     if (new_stream)
10367       gst_qtdemux_stream_free (qtdemux, stream);
10368     return FALSE;
10369   }
10370 existing_stream:
10371   {
10372     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10373         track_id);
10374     if (new_stream)
10375       gst_qtdemux_stream_free (qtdemux, stream);
10376     return TRUE;
10377   }
10378 unknown_stream:
10379   {
10380     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10381         GST_FOURCC_ARGS (stream->subtype));
10382     if (new_stream)
10383       gst_qtdemux_stream_free (qtdemux, stream);
10384     return TRUE;
10385   }
10386 too_many_streams:
10387   {
10388     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10389         (_("This file contains too many streams. Only playing first %d"),
10390             GST_QTDEMUX_MAX_STREAMS), (NULL));
10391     return TRUE;
10392   }
10393 }
10394
10395 /* If we can estimate the overall bitrate, and don't have information about the
10396  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10397  * the overall bitrate minus the sum of the bitrates of all other streams. This
10398  * should be useful for the common case where we have one audio and one video
10399  * stream and can estimate the bitrate of one, but not the other. */
10400 static void
10401 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10402 {
10403   QtDemuxStream *stream = NULL;
10404   gint64 size, sys_bitrate, sum_bitrate = 0;
10405   GstClockTime duration;
10406   gint i;
10407   guint bitrate;
10408
10409   if (qtdemux->fragmented)
10410     return;
10411
10412   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10413
10414   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10415       || size <= 0) {
10416     GST_DEBUG_OBJECT (qtdemux,
10417         "Size in bytes of the stream not known - bailing");
10418     return;
10419   }
10420
10421   /* Subtract the header size */
10422   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10423       size, qtdemux->header_size);
10424
10425   if (size < qtdemux->header_size)
10426     return;
10427
10428   size = size - qtdemux->header_size;
10429
10430   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
10431       duration == GST_CLOCK_TIME_NONE) {
10432     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10433     return;
10434   }
10435
10436   for (i = 0; i < qtdemux->n_streams; i++) {
10437     switch (qtdemux->streams[i]->subtype) {
10438       case FOURCC_soun:
10439       case FOURCC_vide:
10440         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10441             qtdemux->streams[i]->caps);
10442         /* retrieve bitrate, prefer avg then max */
10443         bitrate = 0;
10444         if (qtdemux->streams[i]->pending_tags) {
10445           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10446               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10447           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10448           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10449               GST_TAG_NOMINAL_BITRATE, &bitrate);
10450           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10451           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10452               GST_TAG_BITRATE, &bitrate);
10453           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10454         }
10455         if (bitrate)
10456           sum_bitrate += bitrate;
10457         else {
10458           if (stream) {
10459             GST_DEBUG_OBJECT (qtdemux,
10460                 ">1 stream with unknown bitrate - bailing");
10461             return;
10462           } else
10463             stream = qtdemux->streams[i];
10464         }
10465
10466       default:
10467         /* For other subtypes, we assume no significant impact on bitrate */
10468         break;
10469     }
10470   }
10471
10472   if (!stream) {
10473     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10474     return;
10475   }
10476
10477   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10478
10479   if (sys_bitrate < sum_bitrate) {
10480     /* This can happen, since sum_bitrate might be derived from maximum
10481      * bitrates and not average bitrates */
10482     GST_DEBUG_OBJECT (qtdemux,
10483         "System bitrate less than sum bitrate - bailing");
10484     return;
10485   }
10486
10487   bitrate = sys_bitrate - sum_bitrate;
10488   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10489       ", Stream bitrate = %u", sys_bitrate, bitrate);
10490
10491   if (!stream->pending_tags)
10492     stream->pending_tags = gst_tag_list_new_empty ();
10493
10494   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10495       GST_TAG_BITRATE, bitrate, NULL);
10496 }
10497
10498 static GstFlowReturn
10499 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10500 {
10501   gint i;
10502   GstFlowReturn ret = GST_FLOW_OK;
10503
10504   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10505
10506   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10507     QtDemuxStream *stream = qtdemux->streams[i];
10508     guint32 sample_num = 0;
10509
10510     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10511         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10512
10513     if (qtdemux->fragmented) {
10514       /* need all moov samples first */
10515       GST_OBJECT_LOCK (qtdemux);
10516       while (stream->n_samples == 0)
10517         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10518           break;
10519       GST_OBJECT_UNLOCK (qtdemux);
10520     } else {
10521       /* discard any stray moof */
10522       qtdemux->moof_offset = 0;
10523     }
10524
10525     /* prepare braking */
10526     if (ret != GST_FLOW_ERROR)
10527       ret = GST_FLOW_OK;
10528
10529     /* in pull mode, we should have parsed some sample info by now;
10530      * and quite some code will not handle no samples.
10531      * in push mode, we'll just have to deal with it */
10532     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10533       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10534       gst_qtdemux_remove_stream (qtdemux, i);
10535       i--;
10536       continue;
10537     }
10538
10539     /* parse the initial sample for use in setting the frame rate cap */
10540     while (sample_num == 0 && sample_num < stream->n_samples) {
10541       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10542         break;
10543       ++sample_num;
10544     }
10545     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10546       stream->first_duration = stream->samples[0].duration;
10547       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10548           stream->track_id, stream->first_duration);
10549     }
10550   }
10551
10552   return ret;
10553 }
10554
10555 static GstFlowReturn
10556 qtdemux_expose_streams (GstQTDemux * qtdemux)
10557 {
10558   gint i;
10559   GstFlowReturn ret = GST_FLOW_OK;
10560   GSList *oldpads = NULL;
10561   GSList *iter;
10562
10563   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10564
10565   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10566     QtDemuxStream *stream = qtdemux->streams[i];
10567     GstPad *oldpad = stream->pad;
10568     GstTagList *list;
10569
10570     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10571         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10572
10573     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
10574         stream->track_id == qtdemux->chapters_track_id) {
10575       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
10576          so that it doesn't look like a subtitle track */
10577       gst_qtdemux_remove_stream (qtdemux, i);
10578       i--;
10579       continue;
10580     }
10581
10582     /* now we have all info and can expose */
10583     list = stream->pending_tags;
10584     stream->pending_tags = NULL;
10585     if (oldpad)
10586       oldpads = g_slist_prepend (oldpads, oldpad);
10587     gst_qtdemux_add_stream (qtdemux, stream, list);
10588   }
10589
10590   gst_qtdemux_guess_bitrate (qtdemux);
10591
10592   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
10593
10594   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
10595     GstPad *oldpad = iter->data;
10596
10597     gst_pad_push_event (oldpad, gst_event_new_eos ());
10598     gst_pad_set_active (oldpad, FALSE);
10599     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
10600     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
10601     gst_object_unref (oldpad);
10602   }
10603
10604   /* check if we should post a redirect in case there is a single trak
10605    * and it is a redirecting trak */
10606   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
10607     GstMessage *m;
10608
10609     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
10610         "an external content");
10611     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
10612         gst_structure_new ("redirect",
10613             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
10614             NULL));
10615     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
10616     qtdemux->posted_redirect = TRUE;
10617   }
10618
10619   for (i = 0; i < qtdemux->n_streams; i++) {
10620     QtDemuxStream *stream = qtdemux->streams[i];
10621
10622     qtdemux_do_allocation (qtdemux, stream);
10623   }
10624
10625   qtdemux->exposed = TRUE;
10626   return ret;
10627 }
10628
10629 /* check if major or compatible brand is 3GP */
10630 static inline gboolean
10631 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
10632 {
10633   if (major) {
10634     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10635         FOURCC_3g__);
10636   } else if (qtdemux->comp_brands != NULL) {
10637     GstMapInfo map;
10638     guint8 *data;
10639     gsize size;
10640     gboolean res = FALSE;
10641
10642     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
10643     data = map.data;
10644     size = map.size;
10645     while (size >= 4) {
10646       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10647           FOURCC_3g__);
10648       data += 4;
10649       size -= 4;
10650     }
10651     gst_buffer_unmap (qtdemux->comp_brands, &map);
10652     return res;
10653   } else {
10654     return FALSE;
10655   }
10656 }
10657
10658 /* check if tag is a spec'ed 3GP tag keyword storing a string */
10659 static inline gboolean
10660 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
10661 {
10662   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
10663       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
10664       || fourcc == FOURCC_albm;
10665 }
10666
10667 static void
10668 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
10669     const char *tag, const char *dummy, GNode * node)
10670 {
10671   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10672   int offset;
10673   char *name;
10674   gchar *data;
10675   gdouble longitude, latitude, altitude;
10676   gint len;
10677
10678   len = QT_UINT32 (node->data);
10679   if (len <= 14)
10680     goto short_read;
10681
10682   data = node->data;
10683   offset = 14;
10684
10685   /* TODO: language code skipped */
10686
10687   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
10688
10689   if (!name) {
10690     /* do not alarm in trivial case, but bail out otherwise */
10691     if (*(data + offset) != 0) {
10692       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
10693           "giving up", tag);
10694     }
10695   } else {
10696     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10697         GST_TAG_GEO_LOCATION_NAME, name, NULL);
10698     offset += strlen (name);
10699     g_free (name);
10700   }
10701
10702   if (len < offset + 2 + 4 + 4 + 4)
10703     goto short_read;
10704
10705   /* +1 +1 = skip null-terminator and location role byte */
10706   offset += 1 + 1;
10707   /* table in spec says unsigned, semantics say negative has meaning ... */
10708   longitude = QT_SFP32 (data + offset);
10709
10710   offset += 4;
10711   latitude = QT_SFP32 (data + offset);
10712
10713   offset += 4;
10714   altitude = QT_SFP32 (data + offset);
10715
10716   /* one invalid means all are invalid */
10717   if (longitude >= -180.0 && longitude <= 180.0 &&
10718       latitude >= -90.0 && latitude <= 90.0) {
10719     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10720         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
10721         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
10722         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
10723   }
10724
10725   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
10726
10727   return;
10728
10729   /* ERRORS */
10730 short_read:
10731   {
10732     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
10733     return;
10734   }
10735 }
10736
10737
10738 static void
10739 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
10740     const char *tag, const char *dummy, GNode * node)
10741 {
10742   guint16 y;
10743   GDate *date;
10744   gint len;
10745
10746   len = QT_UINT32 (node->data);
10747   if (len < 14)
10748     return;
10749
10750   y = QT_UINT16 ((guint8 *) node->data + 12);
10751   if (y == 0) {
10752     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
10753     return;
10754   }
10755   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
10756
10757   date = g_date_new_dmy (1, 1, y);
10758   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10759   g_date_free (date);
10760 }
10761
10762 static void
10763 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
10764     const char *tag, const char *dummy, GNode * node)
10765 {
10766   int offset;
10767   char *tag_str = NULL;
10768   guint8 *entity;
10769   guint16 table;
10770   gint len;
10771
10772   len = QT_UINT32 (node->data);
10773   if (len <= 20)
10774     goto short_read;
10775
10776   offset = 12;
10777   entity = (guint8 *) node->data + offset;
10778   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
10779     GST_DEBUG_OBJECT (qtdemux,
10780         "classification info: %c%c%c%c invalid classification entity",
10781         entity[0], entity[1], entity[2], entity[3]);
10782     return;
10783   }
10784
10785   offset += 4;
10786   table = QT_UINT16 ((guint8 *) node->data + offset);
10787
10788   /* Language code skipped */
10789
10790   offset += 4;
10791
10792   /* Tag format: "XXXX://Y[YYYY]/classification info string"
10793    * XXXX: classification entity, fixed length 4 chars.
10794    * Y[YYYY]: classification table, max 5 chars.
10795    */
10796   tag_str = g_strdup_printf ("----://%u/%s",
10797       table, (char *) node->data + offset);
10798
10799   /* memcpy To be sure we're preserving byte order */
10800   memcpy (tag_str, entity, 4);
10801   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
10802
10803   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
10804
10805   g_free (tag_str);
10806
10807   return;
10808
10809   /* ERRORS */
10810 short_read:
10811   {
10812     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
10813     return;
10814   }
10815 }
10816
10817 static gboolean
10818 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
10819     const char *tag, const char *dummy, GNode * node)
10820 {
10821   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10822   GNode *data;
10823   char *s;
10824   int len;
10825   guint32 type;
10826   int offset;
10827   gboolean ret = TRUE;
10828   const gchar *charset = NULL;
10829
10830   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10831   if (data) {
10832     len = QT_UINT32 (data->data);
10833     type = QT_UINT32 ((guint8 *) data->data + 8);
10834     if (type == 0x00000001 && len > 16) {
10835       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
10836           env_vars);
10837       if (s) {
10838         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10839         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10840         g_free (s);
10841       } else {
10842         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10843       }
10844     }
10845   } else {
10846     len = QT_UINT32 (node->data);
10847     type = QT_UINT32 ((guint8 *) node->data + 4);
10848     if ((type >> 24) == 0xa9) {
10849       gint str_len;
10850       gint lang_code;
10851
10852       /* Type starts with the (C) symbol, so the next data is a list
10853        * of (string size(16), language code(16), string) */
10854
10855       str_len = QT_UINT16 ((guint8 *) node->data + 8);
10856       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
10857
10858       /* the string + fourcc + size + 2 16bit fields,
10859        * means that there are more tags in this atom */
10860       if (len > str_len + 8 + 4) {
10861         /* TODO how to represent the same tag in different languages? */
10862         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
10863             "text alternatives, reading only first one");
10864       }
10865
10866       offset = 12;
10867       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
10868       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
10869
10870       if (lang_code < 0x800) {  /* MAC encoded string */
10871         charset = "mac";
10872       }
10873     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
10874             QT_FOURCC ((guint8 *) node->data + 4))) {
10875       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
10876
10877       /* we go for 3GP style encoding if major brands claims so,
10878        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
10879       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10880           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
10881               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
10882         offset = 14;
10883         /* 16-bit Language code is ignored here as well */
10884         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
10885       } else {
10886         goto normal;
10887       }
10888     } else {
10889     normal:
10890       offset = 8;
10891       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
10892       ret = FALSE;              /* may have to fallback */
10893     }
10894     if (charset) {
10895       GError *err = NULL;
10896
10897       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
10898           charset, NULL, NULL, &err);
10899       if (err) {
10900         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
10901             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
10902             err->message);
10903         g_error_free (err);
10904       }
10905     } else {
10906       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10907           len - offset, env_vars);
10908     }
10909     if (s) {
10910       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10911       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10912       g_free (s);
10913       ret = TRUE;
10914     } else {
10915       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10916     }
10917   }
10918   return ret;
10919 }
10920
10921 static void
10922 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
10923     const char *tag, const char *dummy, GNode * node)
10924 {
10925   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
10926 }
10927
10928 static void
10929 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
10930     const char *tag, const char *dummy, GNode * node)
10931 {
10932   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10933   guint8 *data;
10934   char *s, *t, *k = NULL;
10935   int len;
10936   int offset;
10937   int count;
10938
10939   /* first try normal string tag if major brand not 3GP */
10940   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
10941     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
10942       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
10943        * let's try it 3gpp way after minor safety check */
10944       data = node->data;
10945       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
10946         return;
10947     } else
10948       return;
10949   }
10950
10951   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
10952
10953   data = node->data;
10954
10955   len = QT_UINT32 (data);
10956   if (len < 15)
10957     goto short_read;
10958
10959   count = QT_UINT8 (data + 14);
10960   offset = 15;
10961   for (; count; count--) {
10962     gint slen;
10963
10964     if (offset + 1 > len)
10965       goto short_read;
10966     slen = QT_UINT8 (data + offset);
10967     offset += 1;
10968     if (offset + slen > len)
10969       goto short_read;
10970     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10971         slen, env_vars);
10972     if (s) {
10973       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
10974       if (k) {
10975         t = g_strjoin (",", k, s, NULL);
10976         g_free (s);
10977         g_free (k);
10978         k = t;
10979       } else {
10980         k = s;
10981       }
10982     } else {
10983       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
10984     }
10985     offset += slen;
10986   }
10987
10988 done:
10989   if (k) {
10990     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
10991     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
10992   }
10993   g_free (k);
10994
10995   return;
10996
10997   /* ERRORS */
10998 short_read:
10999   {
11000     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
11001     goto done;
11002   }
11003 }
11004
11005 static void
11006 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
11007     const char *tag1, const char *tag2, GNode * node)
11008 {
11009   GNode *data;
11010   int len;
11011   int type;
11012   int n1, n2;
11013
11014   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11015   if (data) {
11016     len = QT_UINT32 (data->data);
11017     type = QT_UINT32 ((guint8 *) data->data + 8);
11018     if (type == 0x00000000 && len >= 22) {
11019       n1 = QT_UINT16 ((guint8 *) data->data + 18);
11020       n2 = QT_UINT16 ((guint8 *) data->data + 20);
11021       if (n1 > 0) {
11022         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
11023         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
11024       }
11025       if (n2 > 0) {
11026         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
11027         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
11028       }
11029     }
11030   }
11031 }
11032
11033 static void
11034 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
11035     const char *tag1, const char *dummy, GNode * node)
11036 {
11037   GNode *data;
11038   int len;
11039   int type;
11040   int n1;
11041
11042   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11043   if (data) {
11044     len = QT_UINT32 (data->data);
11045     type = QT_UINT32 ((guint8 *) data->data + 8);
11046     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
11047     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11048     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
11049       n1 = QT_UINT16 ((guint8 *) data->data + 16);
11050       if (n1) {
11051         /* do not add bpm=0 */
11052         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
11053         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
11054             NULL);
11055       }
11056     }
11057   }
11058 }
11059
11060 static void
11061 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
11062     const char *tag1, const char *dummy, GNode * node)
11063 {
11064   GNode *data;
11065   int len;
11066   int type;
11067   guint32 num;
11068
11069   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11070   if (data) {
11071     len = QT_UINT32 (data->data);
11072     type = QT_UINT32 ((guint8 *) data->data + 8);
11073     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
11074     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
11075     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
11076       num = QT_UINT32 ((guint8 *) data->data + 16);
11077       if (num) {
11078         /* do not add num=0 */
11079         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
11080         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
11081       }
11082     }
11083   }
11084 }
11085
11086 static void
11087 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
11088     const char *tag1, const char *dummy, GNode * node)
11089 {
11090   GNode *data;
11091   int len;
11092   int type;
11093   GstSample *sample;
11094
11095   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11096   if (data) {
11097     len = QT_UINT32 (data->data);
11098     type = QT_UINT32 ((guint8 *) data->data + 8);
11099     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
11100     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
11101       if ((sample =
11102               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
11103                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
11104         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
11105         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
11106         gst_sample_unref (sample);
11107       }
11108     }
11109   }
11110 }
11111
11112 static void
11113 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
11114     const char *tag, const char *dummy, GNode * node)
11115 {
11116   GNode *data;
11117   char *s;
11118   int len;
11119   int type;
11120
11121   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11122   if (data) {
11123     len = QT_UINT32 (data->data);
11124     type = QT_UINT32 ((guint8 *) data->data + 8);
11125     if (type == 0x00000001 && len > 16) {
11126       guint y, m = 1, d = 1;
11127       gint ret;
11128
11129       s = g_strndup ((char *) data->data + 16, len - 16);
11130       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
11131       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
11132       if (ret >= 1 && y > 1500 && y < 3000) {
11133         GDate *date;
11134
11135         date = g_date_new_dmy (d, m, y);
11136         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11137         g_date_free (date);
11138       } else {
11139         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
11140       }
11141       g_free (s);
11142     }
11143   }
11144 }
11145
11146 static void
11147 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
11148     const char *tag, const char *dummy, GNode * node)
11149 {
11150   GNode *data;
11151
11152   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11153
11154   /* re-route to normal string tag if major brand says so
11155    * or no data atom and compatible brand suggests so */
11156   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11157       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
11158     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
11159     return;
11160   }
11161
11162   if (data) {
11163     guint len, type, n;
11164
11165     len = QT_UINT32 (data->data);
11166     type = QT_UINT32 ((guint8 *) data->data + 8);
11167     if (type == 0x00000000 && len >= 18) {
11168       n = QT_UINT16 ((guint8 *) data->data + 16);
11169       if (n > 0) {
11170         const gchar *genre;
11171
11172         genre = gst_tag_id3_genre_get (n - 1);
11173         if (genre != NULL) {
11174           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
11175           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
11176         }
11177       }
11178     }
11179   }
11180 }
11181
11182 static void
11183 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
11184     const gchar * tag, guint8 * data, guint32 datasize)
11185 {
11186   gdouble value;
11187   gchar *datacopy;
11188
11189   /* make a copy to have \0 at the end */
11190   datacopy = g_strndup ((gchar *) data, datasize);
11191
11192   /* convert the str to double */
11193   if (sscanf (datacopy, "%lf", &value) == 1) {
11194     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
11195     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
11196   } else {
11197     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
11198         datacopy);
11199   }
11200   g_free (datacopy);
11201 }
11202
11203
11204 static void
11205 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
11206     const char *tag, const char *tag_bis, GNode * node)
11207 {
11208   GNode *mean;
11209   GNode *name;
11210   GNode *data;
11211   guint32 meansize;
11212   guint32 namesize;
11213   guint32 datatype;
11214   guint32 datasize;
11215   const gchar *meanstr;
11216   const gchar *namestr;
11217
11218   /* checking the whole ---- atom size for consistency */
11219   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11220     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11221     return;
11222   }
11223
11224   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11225   if (!mean) {
11226     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11227     return;
11228   }
11229
11230   meansize = QT_UINT32 (mean->data);
11231   if (meansize <= 12) {
11232     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11233     return;
11234   }
11235   meanstr = ((gchar *) mean->data) + 12;
11236   meansize -= 12;
11237
11238   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11239   if (!name) {
11240     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11241     return;
11242   }
11243
11244   namesize = QT_UINT32 (name->data);
11245   if (namesize <= 12) {
11246     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11247     return;
11248   }
11249   namestr = ((gchar *) name->data) + 12;
11250   namesize -= 12;
11251
11252   /*
11253    * Data atom is:
11254    * uint32 - size
11255    * uint32 - name
11256    * uint8  - version
11257    * uint24 - data type
11258    * uint32 - all 0
11259    * rest   - the data
11260    */
11261   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11262   if (!data) {
11263     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11264     return;
11265   }
11266   datasize = QT_UINT32 (data->data);
11267   if (datasize <= 16) {
11268     GST_WARNING_OBJECT (demux, "Data atom too small");
11269     return;
11270   }
11271   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11272
11273   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11274       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11275     static const struct
11276     {
11277       const gchar name[28];
11278       const gchar tag[28];
11279     } tags[] = {
11280       {
11281       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11282       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11283       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11284       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11285       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11286       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11287       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11288       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11289     };
11290     int i;
11291
11292     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11293       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11294         switch (gst_tag_get_type (tags[i].tag)) {
11295           case G_TYPE_DOUBLE:
11296             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11297                 ((guint8 *) data->data) + 16, datasize - 16);
11298             break;
11299           case G_TYPE_STRING:
11300             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11301             break;
11302           default:
11303             /* not reached */
11304             break;
11305         }
11306         break;
11307       }
11308     }
11309     if (i == G_N_ELEMENTS (tags))
11310       goto unknown_tag;
11311   } else {
11312     goto unknown_tag;
11313   }
11314
11315   return;
11316
11317 /* errors */
11318 unknown_tag:
11319 #ifndef GST_DISABLE_GST_DEBUG
11320   {
11321     gchar *namestr_dbg;
11322     gchar *meanstr_dbg;
11323
11324     meanstr_dbg = g_strndup (meanstr, meansize);
11325     namestr_dbg = g_strndup (namestr, namesize);
11326
11327     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11328         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11329
11330     g_free (namestr_dbg);
11331     g_free (meanstr_dbg);
11332   }
11333 #endif
11334   return;
11335 }
11336
11337 static void
11338 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11339     const char *tag_bis, GNode * node)
11340 {
11341   guint8 *data;
11342   GstBuffer *buf;
11343   guint len;
11344   GstTagList *id32_taglist = NULL;
11345
11346   GST_LOG_OBJECT (demux, "parsing ID32");
11347
11348   data = node->data;
11349   len = GST_READ_UINT32_BE (data);
11350
11351   /* need at least full box and language tag */
11352   if (len < 12 + 2)
11353     return;
11354
11355   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11356   gst_buffer_fill (buf, 0, data + 14, len - 14);
11357
11358   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11359   if (id32_taglist) {
11360     GST_LOG_OBJECT (demux, "parsing ok");
11361     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11362     gst_tag_list_unref (id32_taglist);
11363   } else {
11364     GST_LOG_OBJECT (demux, "parsing failed");
11365   }
11366
11367   gst_buffer_unref (buf);
11368 }
11369
11370 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11371     const char *tag, const char *tag_bis, GNode * node);
11372
11373 /* unmapped tags
11374 FOURCC_pcst -> if media is a podcast -> bool
11375 FOURCC_cpil -> if media is part of a compilation -> bool
11376 FOURCC_pgap -> if media is part of a gapless context -> bool
11377 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11378 */
11379
11380 static const struct
11381 {
11382   guint32 fourcc;
11383   const gchar *gst_tag;
11384   const gchar *gst_tag_bis;
11385   const GstQTDemuxAddTagFunc func;
11386 } add_funcs[] = {
11387   {
11388   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11389   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11390   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11391   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11392   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11393   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11394   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11395   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11396   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11397   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11398   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11399   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11400   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11401   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11402   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11403   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11404   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11405   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11406   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11407   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11408   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11409   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11410   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11411         qtdemux_tag_add_num}, {
11412   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11413         qtdemux_tag_add_num}, {
11414   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11415   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11416   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11417   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11418   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11419   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11420   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11421   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11422   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11423   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11424   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11425   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11426   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11427   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11428   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11429   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11430   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11431   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11432         qtdemux_tag_add_classification}, {
11433   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11434   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11435   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11436
11437     /* This is a special case, some tags are stored in this
11438      * 'reverse dns naming', according to:
11439      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11440      * bug #614471
11441      */
11442   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11443     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11444   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11445 };
11446
11447 struct _GstQtDemuxTagList
11448 {
11449   GstQTDemux *demux;
11450   GstTagList *taglist;
11451 };
11452 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11453
11454 static void
11455 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11456 {
11457   gint len;
11458   guint8 *data;
11459   GstBuffer *buf;
11460   gchar *media_type;
11461   const gchar *style;
11462   GstSample *sample;
11463   GstStructure *s;
11464   guint i;
11465   guint8 ndata[4];
11466   GstQTDemux *demux = qtdemuxtaglist->demux;
11467   GstTagList *taglist = qtdemuxtaglist->taglist;
11468
11469   data = node->data;
11470   len = QT_UINT32 (data);
11471   buf = gst_buffer_new_and_alloc (len);
11472   gst_buffer_fill (buf, 0, data, len);
11473
11474   /* heuristic to determine style of tag */
11475   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11476       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11477     style = "itunes";
11478   else if (demux->major_brand == FOURCC_qt__)
11479     style = "quicktime";
11480   /* fall back to assuming iso/3gp tag style */
11481   else
11482     style = "iso";
11483
11484   /* santize the name for the caps. */
11485   for (i = 0; i < 4; i++) {
11486     guint8 d = data[4 + i];
11487     if (g_ascii_isalnum (d))
11488       ndata[i] = g_ascii_tolower (d);
11489     else
11490       ndata[i] = '_';
11491   }
11492
11493   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11494       ndata[0], ndata[1], ndata[2], ndata[3]);
11495   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11496
11497   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11498   sample = gst_sample_new (buf, NULL, NULL, s);
11499   gst_buffer_unref (buf);
11500   g_free (media_type);
11501
11502   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11503       len, s);
11504
11505   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11506       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11507
11508   gst_sample_unref (sample);
11509 }
11510
11511 static void
11512 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11513 {
11514   GNode *meta;
11515   GNode *ilst;
11516   GNode *xmp_;
11517   GNode *node;
11518   gint i;
11519   GstQtDemuxTagList demuxtaglist;
11520
11521   demuxtaglist.demux = qtdemux;
11522   demuxtaglist.taglist = taglist;
11523
11524   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11525   if (meta != NULL) {
11526     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11527     if (ilst == NULL) {
11528       GST_LOG_OBJECT (qtdemux, "no ilst");
11529       return;
11530     }
11531   } else {
11532     ilst = udta;
11533     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11534   }
11535
11536   i = 0;
11537   while (i < G_N_ELEMENTS (add_funcs)) {
11538     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11539     if (node) {
11540       gint len;
11541
11542       len = QT_UINT32 (node->data);
11543       if (len < 12) {
11544         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11545             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11546       } else {
11547         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11548             add_funcs[i].gst_tag_bis, node);
11549       }
11550       g_node_destroy (node);
11551     } else {
11552       i++;
11553     }
11554   }
11555
11556   /* parsed nodes have been removed, pass along remainder as blob */
11557   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11558       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11559
11560   /* parse up XMP_ node if existing */
11561   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11562   if (xmp_ != NULL) {
11563     GstBuffer *buf;
11564     GstTagList *xmptaglist;
11565
11566     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
11567         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
11568     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
11569     gst_buffer_unref (buf);
11570
11571     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
11572   } else {
11573     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
11574   }
11575 }
11576
11577 typedef struct
11578 {
11579   GstStructure *structure;      /* helper for sort function */
11580   gchar *location;
11581   guint min_req_bitrate;
11582   guint min_req_qt_version;
11583 } GstQtReference;
11584
11585 static gint
11586 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
11587 {
11588   GstQtReference *ref_a = (GstQtReference *) a;
11589   GstQtReference *ref_b = (GstQtReference *) b;
11590
11591   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
11592     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
11593
11594   /* known bitrates go before unknown; higher bitrates go first */
11595   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
11596 }
11597
11598 /* sort the redirects and post a message for the application.
11599  */
11600 static void
11601 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
11602 {
11603   GstQtReference *best;
11604   GstStructure *s;
11605   GstMessage *msg;
11606   GValue list_val = { 0, };
11607   GList *l;
11608
11609   g_assert (references != NULL);
11610
11611   references = g_list_sort (references, qtdemux_redirects_sort_func);
11612
11613   best = (GstQtReference *) references->data;
11614
11615   g_value_init (&list_val, GST_TYPE_LIST);
11616
11617   for (l = references; l != NULL; l = l->next) {
11618     GstQtReference *ref = (GstQtReference *) l->data;
11619     GValue struct_val = { 0, };
11620
11621     ref->structure = gst_structure_new ("redirect",
11622         "new-location", G_TYPE_STRING, ref->location, NULL);
11623
11624     if (ref->min_req_bitrate > 0) {
11625       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
11626           ref->min_req_bitrate, NULL);
11627     }
11628
11629     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
11630     g_value_set_boxed (&struct_val, ref->structure);
11631     gst_value_list_append_value (&list_val, &struct_val);
11632     g_value_unset (&struct_val);
11633     /* don't free anything here yet, since we need best->structure below */
11634   }
11635
11636   g_assert (best != NULL);
11637   s = gst_structure_copy (best->structure);
11638
11639   if (g_list_length (references) > 1) {
11640     gst_structure_set_value (s, "locations", &list_val);
11641   }
11642
11643   g_value_unset (&list_val);
11644
11645   for (l = references; l != NULL; l = l->next) {
11646     GstQtReference *ref = (GstQtReference *) l->data;
11647
11648     gst_structure_free (ref->structure);
11649     g_free (ref->location);
11650     g_free (ref);
11651   }
11652   g_list_free (references);
11653
11654   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
11655   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
11656   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
11657   qtdemux->posted_redirect = TRUE;
11658 }
11659
11660 /* look for redirect nodes, collect all redirect information and
11661  * process it.
11662  */
11663 static gboolean
11664 qtdemux_parse_redirects (GstQTDemux * qtdemux)
11665 {
11666   GNode *rmra, *rmda, *rdrf;
11667
11668   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
11669   if (rmra) {
11670     GList *redirects = NULL;
11671
11672     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
11673     while (rmda) {
11674       GstQtReference ref = { NULL, NULL, 0, 0 };
11675       GNode *rmdr, *rmvc;
11676
11677       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
11678         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
11679         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
11680             ref.min_req_bitrate);
11681       }
11682
11683       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
11684         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
11685         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
11686
11687 #ifndef GST_DISABLE_GST_DEBUG
11688         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
11689 #endif
11690         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
11691
11692         GST_LOG_OBJECT (qtdemux,
11693             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
11694             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
11695             bitmask, check_type);
11696         if (package == FOURCC_qtim && check_type == 0) {
11697           ref.min_req_qt_version = version;
11698         }
11699       }
11700
11701       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
11702       if (rdrf) {
11703         guint32 ref_type;
11704         guint8 *ref_data;
11705         guint ref_len;
11706
11707         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
11708         if (ref_len > 20) {
11709           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
11710           ref_data = (guint8 *) rdrf->data + 20;
11711           if (ref_type == FOURCC_alis) {
11712             guint record_len, record_version, fn_len;
11713
11714             if (ref_len > 70) {
11715               /* MacOSX alias record, google for alias-layout.txt */
11716               record_len = QT_UINT16 (ref_data + 4);
11717               record_version = QT_UINT16 (ref_data + 4 + 2);
11718               fn_len = QT_UINT8 (ref_data + 50);
11719               if (record_len > 50 && record_version == 2 && fn_len > 0) {
11720                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
11721               }
11722             } else {
11723               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
11724                   ref_len);
11725             }
11726           } else if (ref_type == FOURCC_url_) {
11727             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
11728           } else {
11729             GST_DEBUG_OBJECT (qtdemux,
11730                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
11731                 GST_FOURCC_ARGS (ref_type));
11732           }
11733           if (ref.location != NULL) {
11734             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
11735             redirects =
11736                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
11737           } else {
11738             GST_WARNING_OBJECT (qtdemux,
11739                 "Failed to extract redirect location from rdrf atom");
11740           }
11741         } else {
11742           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
11743         }
11744       }
11745
11746       /* look for others */
11747       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
11748     }
11749
11750     if (redirects != NULL) {
11751       qtdemux_process_redirects (qtdemux, redirects);
11752     }
11753   }
11754   return TRUE;
11755 }
11756
11757 static GstTagList *
11758 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
11759 {
11760   const gchar *fmt;
11761
11762   if (tags == NULL) {
11763     tags = gst_tag_list_new_empty ();
11764     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
11765   }
11766
11767   if (qtdemux->major_brand == FOURCC_mjp2)
11768     fmt = "Motion JPEG 2000";
11769   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
11770     fmt = "3GP";
11771   else if (qtdemux->major_brand == FOURCC_qt__)
11772     fmt = "Quicktime";
11773   else if (qtdemux->fragmented)
11774     fmt = "ISO fMP4";
11775   else
11776     fmt = "ISO MP4/M4A";
11777
11778   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
11779       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
11780
11781   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
11782       fmt, NULL);
11783
11784   return tags;
11785 }
11786
11787 /* we have read th complete moov node now.
11788  * This function parses all of the relevant info, creates the traks and
11789  * prepares all data structures for playback
11790  */
11791 static gboolean
11792 qtdemux_parse_tree (GstQTDemux * qtdemux)
11793 {
11794   GNode *mvhd;
11795   GNode *trak;
11796   GNode *udta;
11797   GNode *mvex;
11798   GstClockTime duration;
11799   GNode *pssh;
11800   guint64 creation_time;
11801   GstDateTime *datetime = NULL;
11802   gint version;
11803
11804   /* make sure we have a usable taglist */
11805   if (!qtdemux->tag_list) {
11806     qtdemux->tag_list = gst_tag_list_new_empty ();
11807     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11808   } else {
11809     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11810   }
11811
11812   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
11813   if (mvhd == NULL) {
11814     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
11815     return qtdemux_parse_redirects (qtdemux);
11816   }
11817
11818   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
11819   if (version == 1) {
11820     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
11821     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
11822     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
11823   } else if (version == 0) {
11824     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
11825     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
11826     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
11827   } else {
11828     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
11829     return FALSE;
11830   }
11831
11832   /* Moving qt creation time (secs since 1904) to unix time */
11833   if (creation_time != 0) {
11834     /* Try to use epoch first as it should be faster and more commonly found */
11835     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
11836       GTimeVal now;
11837
11838       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
11839       /* some data cleansing sanity */
11840       g_get_current_time (&now);
11841       if (now.tv_sec + 24 * 3600 < creation_time) {
11842         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
11843       } else {
11844         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
11845       }
11846     } else {
11847       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
11848       GDateTime *dt, *dt_local;
11849
11850       dt = g_date_time_add_seconds (base_dt, creation_time);
11851       dt_local = g_date_time_to_local (dt);
11852       datetime = gst_date_time_new_from_g_date_time (dt_local);
11853
11854       g_date_time_unref (base_dt);
11855       g_date_time_unref (dt);
11856     }
11857   }
11858   if (datetime) {
11859     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
11860     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
11861         datetime, NULL);
11862     gst_date_time_unref (datetime);
11863   }
11864
11865   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
11866   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
11867
11868   /* check for fragmented file and get some (default) data */
11869   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
11870   if (mvex) {
11871     GNode *mehd;
11872     GstByteReader mehd_data;
11873
11874     /* let track parsing or anyone know weird stuff might happen ... */
11875     qtdemux->fragmented = TRUE;
11876
11877     /* compensate for total duration */
11878     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
11879     if (mehd)
11880       qtdemux_parse_mehd (qtdemux, &mehd_data);
11881   }
11882
11883   /* set duration in the segment info */
11884   gst_qtdemux_get_duration (qtdemux, &duration);
11885   if (duration) {
11886     qtdemux->segment.duration = duration;
11887     /* also do not exceed duration; stop is set that way post seek anyway,
11888      * and segment activation falls back to duration,
11889      * whereas loop only checks stop, so let's align this here as well */
11890     qtdemux->segment.stop = duration;
11891   }
11892
11893   /* parse all traks */
11894   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
11895   while (trak) {
11896     qtdemux_parse_trak (qtdemux, trak);
11897     /* iterate all siblings */
11898     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
11899   }
11900
11901   if (!qtdemux->tag_list) {
11902     GST_DEBUG_OBJECT (qtdemux, "new tag list");
11903     qtdemux->tag_list = gst_tag_list_new_empty ();
11904     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11905   } else {
11906     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11907   }
11908
11909   /* find tags */
11910   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
11911   if (udta) {
11912     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11913   } else {
11914     GST_LOG_OBJECT (qtdemux, "No udta node found.");
11915   }
11916
11917   /* maybe also some tags in meta box */
11918   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
11919   if (udta) {
11920     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
11921     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11922   } else {
11923     GST_LOG_OBJECT (qtdemux, "No meta node found.");
11924   }
11925
11926   /* parse any protection system info */
11927   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
11928   while (pssh) {
11929     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
11930     qtdemux_parse_pssh (qtdemux, pssh);
11931     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
11932   }
11933
11934   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
11935
11936   return TRUE;
11937 }
11938
11939 /* taken from ffmpeg */
11940 static int
11941 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
11942 {
11943   int count = 4;
11944   int len = 0;
11945
11946   while (count--) {
11947     int c;
11948
11949     if (ptr >= end)
11950       return -1;
11951
11952     c = *ptr++;
11953     len = (len << 7) | (c & 0x7f);
11954     if (!(c & 0x80))
11955       break;
11956   }
11957   *end_out = ptr;
11958   return len;
11959 }
11960
11961 /* this can change the codec originally present in @list */
11962 static void
11963 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
11964     GNode * esds, GstTagList * list)
11965 {
11966   int len = QT_UINT32 (esds->data);
11967   guint8 *ptr = esds->data;
11968   guint8 *end = ptr + len;
11969   int tag;
11970   guint8 *data_ptr = NULL;
11971   int data_len = 0;
11972   guint8 object_type_id = 0;
11973   const char *codec_name = NULL;
11974   GstCaps *caps = NULL;
11975
11976   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
11977   ptr += 8;
11978   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
11979   ptr += 4;
11980   while (ptr + 1 < end) {
11981     tag = QT_UINT8 (ptr);
11982     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
11983     ptr++;
11984     len = read_descr_size (ptr, end, &ptr);
11985     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
11986
11987     /* Check the stated amount of data is available for reading */
11988     if (len < 0 || ptr + len > end)
11989       break;
11990
11991     switch (tag) {
11992       case ES_DESCRIPTOR_TAG:
11993         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
11994         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
11995         ptr += 3;
11996         break;
11997       case DECODER_CONFIG_DESC_TAG:{
11998         guint max_bitrate, avg_bitrate;
11999
12000         object_type_id = QT_UINT8 (ptr);
12001         max_bitrate = QT_UINT32 (ptr + 5);
12002         avg_bitrate = QT_UINT32 (ptr + 9);
12003         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
12004         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
12005         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
12006         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
12007         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
12008         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
12009           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12010               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
12011         }
12012         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
12013           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
12014               avg_bitrate, NULL);
12015         }
12016         ptr += 13;
12017         break;
12018       }
12019       case DECODER_SPECIFIC_INFO_TAG:
12020         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
12021         if (object_type_id == 0xe0 && len == 0x40) {
12022           guint8 *data;
12023           GstStructure *s;
12024           guint32 clut[16];
12025           gint i;
12026
12027           GST_DEBUG_OBJECT (qtdemux,
12028               "Have VOBSUB palette. Creating palette event");
12029           /* move to decConfigDescr data and read palette */
12030           data = ptr;
12031           for (i = 0; i < 16; i++) {
12032             clut[i] = QT_UINT32 (data);
12033             data += 4;
12034           }
12035
12036           s = gst_structure_new ("application/x-gst-dvd", "event",
12037               G_TYPE_STRING, "dvd-spu-clut-change",
12038               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
12039               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
12040               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
12041               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
12042               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
12043               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
12044               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
12045               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
12046               NULL);
12047
12048           /* store event and trigger custom processing */
12049           stream->pending_event =
12050               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
12051         } else {
12052           /* Generic codec_data handler puts it on the caps */
12053           data_ptr = ptr;
12054           data_len = len;
12055         }
12056
12057         ptr += len;
12058         break;
12059       case SL_CONFIG_DESC_TAG:
12060         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
12061         ptr += 1;
12062         break;
12063       default:
12064         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
12065             tag);
12066         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
12067         ptr += len;
12068         break;
12069     }
12070   }
12071
12072   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
12073    * in use, and should also be used to override some other parameters for some
12074    * codecs. */
12075   switch (object_type_id) {
12076     case 0x20:                 /* MPEG-4 */
12077       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
12078        * profile_and_level_indication */
12079       if (data_ptr != NULL && data_len >= 5 &&
12080           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
12081         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
12082             data_ptr + 4, data_len - 4);
12083       }
12084       break;                    /* Nothing special needed here */
12085     case 0x21:                 /* H.264 */
12086       codec_name = "H.264 / AVC";
12087       caps = gst_caps_new_simple ("video/x-h264",
12088           "stream-format", G_TYPE_STRING, "avc",
12089           "alignment", G_TYPE_STRING, "au", NULL);
12090       break;
12091     case 0x40:                 /* AAC (any) */
12092     case 0x66:                 /* AAC Main */
12093     case 0x67:                 /* AAC LC */
12094     case 0x68:                 /* AAC SSR */
12095       /* Override channels and rate based on the codec_data, as it's often
12096        * wrong. */
12097       /* Only do so for basic setup without HE-AAC extension */
12098       if (data_ptr && data_len == 2) {
12099         guint channels, rateindex, rate;
12100
12101         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
12102         channels = (data_ptr[1] & 0x7f) >> 3;
12103         if (channels > 0 && channels < 7) {
12104           stream->n_channels = channels;
12105         } else if (channels == 7) {
12106           stream->n_channels = 8;
12107         }
12108
12109         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
12110         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
12111         if (rate > 0)
12112           stream->rate = rate;
12113       }
12114
12115       /* Set level and profile if possible */
12116       if (data_ptr != NULL && data_len >= 2) {
12117         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
12118             data_ptr, data_len);
12119       }
12120       break;
12121     case 0x60:                 /* MPEG-2, various profiles */
12122     case 0x61:
12123     case 0x62:
12124     case 0x63:
12125     case 0x64:
12126     case 0x65:
12127       codec_name = "MPEG-2 video";
12128       caps = gst_caps_new_simple ("video/mpeg",
12129           "mpegversion", G_TYPE_INT, 2,
12130           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12131       break;
12132     case 0x69:                 /* MPEG-2 BC audio */
12133     case 0x6B:                 /* MPEG-1 audio */
12134       caps = gst_caps_new_simple ("audio/mpeg",
12135           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
12136       codec_name = "MPEG-1 audio";
12137       break;
12138     case 0x6A:                 /* MPEG-1 */
12139       codec_name = "MPEG-1 video";
12140       caps = gst_caps_new_simple ("video/mpeg",
12141           "mpegversion", G_TYPE_INT, 1,
12142           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12143       break;
12144     case 0x6C:                 /* MJPEG */
12145       caps =
12146           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12147           NULL);
12148       codec_name = "Motion-JPEG";
12149       break;
12150     case 0x6D:                 /* PNG */
12151       caps =
12152           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
12153           NULL);
12154       codec_name = "PNG still images";
12155       break;
12156     case 0x6E:                 /* JPEG2000 */
12157       codec_name = "JPEG-2000";
12158       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12159       break;
12160     case 0xA4:                 /* Dirac */
12161       codec_name = "Dirac";
12162       caps = gst_caps_new_empty_simple ("video/x-dirac");
12163       break;
12164     case 0xA5:                 /* AC3 */
12165       codec_name = "AC-3 audio";
12166       caps = gst_caps_new_simple ("audio/x-ac3",
12167           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12168       break;
12169     case 0xA9:                 /* AC3 */
12170       codec_name = "DTS audio";
12171       caps = gst_caps_new_simple ("audio/x-dts",
12172           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12173       break;
12174     case 0xE1:                 /* QCELP */
12175       /* QCELP, the codec_data is a riff tag (little endian) with
12176        * 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). */
12177       caps = gst_caps_new_empty_simple ("audio/qcelp");
12178       codec_name = "QCELP";
12179       break;
12180     default:
12181       break;
12182   }
12183
12184   /* If we have a replacement caps, then change our caps for this stream */
12185   if (caps) {
12186     gst_caps_unref (stream->caps);
12187     stream->caps = caps;
12188   }
12189
12190   if (codec_name && list)
12191     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
12192         GST_TAG_AUDIO_CODEC, codec_name, NULL);
12193
12194   /* Add the codec_data attribute to caps, if we have it */
12195   if (data_ptr) {
12196     GstBuffer *buffer;
12197
12198     buffer = gst_buffer_new_and_alloc (data_len);
12199     gst_buffer_fill (buffer, 0, data_ptr, data_len);
12200
12201     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
12202     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
12203
12204     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
12205         buffer, NULL);
12206     gst_buffer_unref (buffer);
12207   }
12208
12209 }
12210
12211 #define _codec(name) \
12212   do { \
12213     if (codec_name) { \
12214       *codec_name = g_strdup (name); \
12215     } \
12216   } while (0)
12217
12218 static GstCaps *
12219 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12220     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12221 {
12222   GstCaps *caps = NULL;
12223   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12224
12225   switch (fourcc) {
12226     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12227       _codec ("PNG still images");
12228       caps = gst_caps_new_empty_simple ("image/png");
12229       break;
12230     case FOURCC_jpeg:
12231       _codec ("JPEG still images");
12232       caps =
12233           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12234           NULL);
12235       break;
12236     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12237     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12238     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12239     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12240       _codec ("Motion-JPEG");
12241       caps =
12242           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12243           NULL);
12244       break;
12245     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12246       _codec ("Motion-JPEG format B");
12247       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12248       break;
12249     case FOURCC_mjp2:
12250       _codec ("JPEG-2000");
12251       /* override to what it should be according to spec, avoid palette_data */
12252       stream->bits_per_sample = 24;
12253       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12254       break;
12255     case FOURCC_SVQ3:
12256       _codec ("Sorensen video v.3");
12257       caps = gst_caps_new_simple ("video/x-svq",
12258           "svqversion", G_TYPE_INT, 3, NULL);
12259       break;
12260     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12261     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12262       _codec ("Sorensen video v.1");
12263       caps = gst_caps_new_simple ("video/x-svq",
12264           "svqversion", G_TYPE_INT, 1, NULL);
12265       break;
12266     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12267       caps = gst_caps_new_empty_simple ("video/x-raw");
12268       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12269       _codec ("Windows Raw RGB");
12270       break;
12271     case FOURCC_raw_:
12272     {
12273       guint16 bps;
12274
12275       bps = QT_UINT16 (stsd_data + 98);
12276       switch (bps) {
12277         case 15:
12278           format = GST_VIDEO_FORMAT_RGB15;
12279           break;
12280         case 16:
12281           format = GST_VIDEO_FORMAT_RGB16;
12282           break;
12283         case 24:
12284           format = GST_VIDEO_FORMAT_RGB;
12285           break;
12286         case 32:
12287           format = GST_VIDEO_FORMAT_ARGB;
12288           break;
12289         default:
12290           /* unknown */
12291           break;
12292       }
12293       break;
12294     }
12295     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12296       format = GST_VIDEO_FORMAT_I420;
12297       break;
12298     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12299     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12300       format = GST_VIDEO_FORMAT_I420;
12301       break;
12302     case FOURCC_2vuy:
12303     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12304       format = GST_VIDEO_FORMAT_UYVY;
12305       break;
12306     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12307       format = GST_VIDEO_FORMAT_v308;
12308       break;
12309     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12310       format = GST_VIDEO_FORMAT_v216;
12311       break;
12312     case FOURCC_v210:
12313       format = GST_VIDEO_FORMAT_v210;
12314       break;
12315     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12316       format = GST_VIDEO_FORMAT_r210;
12317       break;
12318       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12319          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12320          format = GST_VIDEO_FORMAT_v410;
12321          break;
12322        */
12323       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12324        * but different order than AYUV
12325        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12326        format = GST_VIDEO_FORMAT_v408;
12327        break;
12328        */
12329     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12330     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12331       _codec ("MPEG-1 video");
12332       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12333           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12334       break;
12335     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12336     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12337     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12338     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12339     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12340     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12341     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12342     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12343     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12344     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12345     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12346     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12347     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12348     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12349     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12350     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12351     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12352     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12353     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12354     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12355     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12356     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12357     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12358     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12359     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12360     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12361     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12362     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12363     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12364     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12365     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12366     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12367     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12368     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12369     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12370     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12371     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12372     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12373     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12374     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12375     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12376     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12377     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12378     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12379     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12380     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12381       _codec ("MPEG-2 video");
12382       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12383           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12384       break;
12385     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12386       _codec ("GIF still images");
12387       caps = gst_caps_new_empty_simple ("image/gif");
12388       break;
12389     case FOURCC_h263:
12390     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12391     case FOURCC_s263:
12392     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12393       _codec ("H.263");
12394       /* ffmpeg uses the height/width props, don't know why */
12395       caps = gst_caps_new_simple ("video/x-h263",
12396           "variant", G_TYPE_STRING, "itu", NULL);
12397       break;
12398     case FOURCC_mp4v:
12399     case FOURCC_MP4V:
12400       _codec ("MPEG-4 video");
12401       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12402           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12403       break;
12404     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12405     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12406       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12407       caps = gst_caps_new_simple ("video/x-msmpeg",
12408           "msmpegversion", G_TYPE_INT, 43, NULL);
12409       break;
12410     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12411       _codec ("DivX 3");
12412       caps = gst_caps_new_simple ("video/x-divx",
12413           "divxversion", G_TYPE_INT, 3, NULL);
12414       break;
12415     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12416     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12417       _codec ("DivX 4");
12418       caps = gst_caps_new_simple ("video/x-divx",
12419           "divxversion", G_TYPE_INT, 4, NULL);
12420       break;
12421     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12422       _codec ("DivX 5");
12423       caps = gst_caps_new_simple ("video/x-divx",
12424           "divxversion", G_TYPE_INT, 5, NULL);
12425       break;
12426
12427     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
12428       _codec ("FFV1");
12429       caps = gst_caps_new_simple ("video/x-ffv",
12430           "ffvversion", G_TYPE_INT, 1, NULL);
12431       break;
12432
12433     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12434     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12435     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12436     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12437     case FOURCC_FMP4:
12438     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12439       caps = gst_caps_new_simple ("video/mpeg",
12440           "mpegversion", G_TYPE_INT, 4, NULL);
12441       _codec ("MPEG-4");
12442       break;
12443
12444     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12445       _codec ("Cinepak");
12446       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12447       break;
12448     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12449       _codec ("Apple QuickDraw");
12450       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12451       break;
12452     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12453       _codec ("Apple video");
12454       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12455       break;
12456     case FOURCC_H264:
12457     case FOURCC_avc1:
12458       _codec ("H.264 / AVC");
12459       caps = gst_caps_new_simple ("video/x-h264",
12460           "stream-format", G_TYPE_STRING, "avc",
12461           "alignment", G_TYPE_STRING, "au", NULL);
12462       break;
12463     case FOURCC_avc3:
12464       _codec ("H.264 / AVC");
12465       caps = gst_caps_new_simple ("video/x-h264",
12466           "stream-format", G_TYPE_STRING, "avc3",
12467           "alignment", G_TYPE_STRING, "au", NULL);
12468       break;
12469     case FOURCC_H265:
12470     case FOURCC_hvc1:
12471       _codec ("H.265 / HEVC");
12472       caps = gst_caps_new_simple ("video/x-h265",
12473           "stream-format", G_TYPE_STRING, "hvc1",
12474           "alignment", G_TYPE_STRING, "au", NULL);
12475       break;
12476     case FOURCC_hev1:
12477       _codec ("H.265 / HEVC");
12478       caps = gst_caps_new_simple ("video/x-h265",
12479           "stream-format", G_TYPE_STRING, "hev1",
12480           "alignment", G_TYPE_STRING, "au", NULL);
12481       break;
12482     case FOURCC_rle_:
12483       _codec ("Run-length encoding");
12484       caps = gst_caps_new_simple ("video/x-rle",
12485           "layout", G_TYPE_STRING, "quicktime", NULL);
12486       break;
12487     case FOURCC_WRLE:
12488       _codec ("Run-length encoding");
12489       caps = gst_caps_new_simple ("video/x-rle",
12490           "layout", G_TYPE_STRING, "microsoft", NULL);
12491       break;
12492     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12493     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12494       _codec ("Indeo Video 3");
12495       caps = gst_caps_new_simple ("video/x-indeo",
12496           "indeoversion", G_TYPE_INT, 3, NULL);
12497       break;
12498     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12499     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12500       _codec ("Intel Video 4");
12501       caps = gst_caps_new_simple ("video/x-indeo",
12502           "indeoversion", G_TYPE_INT, 4, NULL);
12503       break;
12504     case FOURCC_dvcp:
12505     case FOURCC_dvc_:
12506     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12507     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12508     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12509     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12510     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12511     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12512       _codec ("DV Video");
12513       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12514           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12515       break;
12516     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
12517     case FOURCC_dv5p:          /* DVCPRO50 PAL */
12518       _codec ("DVCPro50 Video");
12519       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12520           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12521       break;
12522     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12523     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12524       _codec ("DVCProHD Video");
12525       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12526           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12527       break;
12528     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12529       _codec ("Apple Graphics (SMC)");
12530       caps = gst_caps_new_empty_simple ("video/x-smc");
12531       break;
12532     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12533       _codec ("VP3");
12534       caps = gst_caps_new_empty_simple ("video/x-vp3");
12535       break;
12536     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12537       _codec ("VP6 Flash");
12538       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12539       break;
12540     case FOURCC_XiTh:
12541       _codec ("Theora");
12542       caps = gst_caps_new_empty_simple ("video/x-theora");
12543       /* theora uses one byte of padding in the data stream because it does not
12544        * allow 0 sized packets while theora does */
12545       stream->padding = 1;
12546       break;
12547     case FOURCC_drac:
12548       _codec ("Dirac");
12549       caps = gst_caps_new_empty_simple ("video/x-dirac");
12550       break;
12551     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12552       _codec ("TIFF still images");
12553       caps = gst_caps_new_empty_simple ("image/tiff");
12554       break;
12555     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12556       _codec ("Apple Intermediate Codec");
12557       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12558       break;
12559     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12560       _codec ("AVID DNxHD");
12561       caps = gst_caps_from_string ("video/x-dnxhd");
12562       break;
12563     case FOURCC_VP80:
12564       _codec ("On2 VP8");
12565       caps = gst_caps_from_string ("video/x-vp8");
12566       break;
12567     case FOURCC_apcs:
12568       _codec ("Apple ProRes LT");
12569       caps =
12570           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
12571           NULL);
12572       break;
12573     case FOURCC_apch:
12574       _codec ("Apple ProRes HQ");
12575       caps =
12576           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
12577           NULL);
12578       break;
12579     case FOURCC_apcn:
12580       _codec ("Apple ProRes");
12581       caps =
12582           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12583           "standard", NULL);
12584       break;
12585     case FOURCC_apco:
12586       _codec ("Apple ProRes Proxy");
12587       caps =
12588           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12589           "proxy", NULL);
12590       break;
12591     case FOURCC_ap4h:
12592       _codec ("Apple ProRes 4444");
12593       caps =
12594           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12595           "4444", NULL);
12596       break;
12597     case FOURCC_vc_1:
12598     case FOURCC_ovc1:
12599       _codec ("VC-1");
12600       caps = gst_caps_new_simple ("video/x-wmv",
12601           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
12602       break;
12603     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
12604     default:
12605     {
12606       char *s, fourstr[5];
12607
12608       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12609       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
12610       caps = gst_caps_new_empty_simple (s);
12611       g_free (s);
12612       break;
12613     }
12614   }
12615
12616   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
12617     GstVideoInfo info;
12618
12619     gst_video_info_init (&info);
12620     gst_video_info_set_format (&info, format, stream->width, stream->height);
12621
12622     caps = gst_video_info_to_caps (&info);
12623     *codec_name = gst_pb_utils_get_codec_description (caps);
12624
12625     /* enable clipping for raw video streams */
12626     stream->need_clip = TRUE;
12627   }
12628
12629   return caps;
12630 }
12631
12632 static GstCaps *
12633 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12634     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
12635 {
12636   GstCaps *caps;
12637   const GstStructure *s;
12638   const gchar *name;
12639   gint endian = 0;
12640   GstAudioFormat format = 0;
12641   gint depth;
12642
12643   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12644
12645   depth = stream->bytes_per_packet * 8;
12646
12647   switch (fourcc) {
12648     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
12649     case FOURCC_raw_:
12650       /* 8-bit audio is unsigned */
12651       if (depth == 8)
12652         format = GST_AUDIO_FORMAT_U8;
12653       /* otherwise it's signed and big-endian just like 'twos' */
12654     case FOURCC_twos:
12655       endian = G_BIG_ENDIAN;
12656       /* fall-through */
12657     case FOURCC_sowt:
12658     {
12659       gchar *str;
12660
12661       if (!endian)
12662         endian = G_LITTLE_ENDIAN;
12663
12664       if (!format)
12665         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
12666
12667       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
12668       _codec (str);
12669       g_free (str);
12670
12671       caps = gst_caps_new_simple ("audio/x-raw",
12672           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12673           "layout", G_TYPE_STRING, "interleaved", NULL);
12674       break;
12675     }
12676     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
12677       _codec ("Raw 64-bit floating-point audio");
12678       caps = gst_caps_new_simple ("audio/x-raw",
12679           "format", G_TYPE_STRING, "F64BE",
12680           "layout", G_TYPE_STRING, "interleaved", NULL);
12681       break;
12682     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
12683       _codec ("Raw 32-bit floating-point audio");
12684       caps = gst_caps_new_simple ("audio/x-raw",
12685           "format", G_TYPE_STRING, "F32BE",
12686           "layout", G_TYPE_STRING, "interleaved", NULL);
12687       break;
12688     case FOURCC_in24:
12689       _codec ("Raw 24-bit PCM audio");
12690       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
12691        * endian later */
12692       caps = gst_caps_new_simple ("audio/x-raw",
12693           "format", G_TYPE_STRING, "S24BE",
12694           "layout", G_TYPE_STRING, "interleaved", NULL);
12695       break;
12696     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
12697       _codec ("Raw 32-bit PCM audio");
12698       caps = gst_caps_new_simple ("audio/x-raw",
12699           "format", G_TYPE_STRING, "S32BE",
12700           "layout", G_TYPE_STRING, "interleaved", NULL);
12701       break;
12702     case FOURCC_ulaw:
12703       _codec ("Mu-law audio");
12704       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
12705       break;
12706     case FOURCC_alaw:
12707       _codec ("A-law audio");
12708       caps = gst_caps_new_empty_simple ("audio/x-alaw");
12709       break;
12710     case 0x0200736d:
12711     case 0x6d730002:
12712       _codec ("Microsoft ADPCM");
12713       /* Microsoft ADPCM-ACM code 2 */
12714       caps = gst_caps_new_simple ("audio/x-adpcm",
12715           "layout", G_TYPE_STRING, "microsoft", NULL);
12716       break;
12717     case 0x1100736d:
12718     case 0x6d730011:
12719       _codec ("DVI/IMA ADPCM");
12720       caps = gst_caps_new_simple ("audio/x-adpcm",
12721           "layout", G_TYPE_STRING, "dvi", NULL);
12722       break;
12723     case 0x1700736d:
12724     case 0x6d730017:
12725       _codec ("DVI/Intel IMA ADPCM");
12726       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
12727       caps = gst_caps_new_simple ("audio/x-adpcm",
12728           "layout", G_TYPE_STRING, "quicktime", NULL);
12729       break;
12730     case 0x5500736d:
12731     case 0x6d730055:
12732       /* MPEG layer 3, CBR only (pre QT4.1) */
12733     case FOURCC__mp3:
12734       _codec ("MPEG-1 layer 3");
12735       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
12736       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
12737           "mpegversion", G_TYPE_INT, 1, NULL);
12738       break;
12739     case 0x20736d:
12740     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
12741       _codec ("EAC-3 audio");
12742       caps = gst_caps_new_simple ("audio/x-eac3",
12743           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12744       stream->sampled = TRUE;
12745       break;
12746     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
12747     case FOURCC_ac_3:
12748       _codec ("AC-3 audio");
12749       caps = gst_caps_new_simple ("audio/x-ac3",
12750           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12751       stream->sampled = TRUE;
12752       break;
12753     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
12754     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
12755       _codec ("DTS audio");
12756       caps = gst_caps_new_simple ("audio/x-dts",
12757           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12758       stream->sampled = TRUE;
12759       break;
12760     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
12761     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
12762       _codec ("DTS-HD audio");
12763       caps = gst_caps_new_simple ("audio/x-dts",
12764           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12765       stream->sampled = TRUE;
12766       break;
12767     case FOURCC_MAC3:
12768       _codec ("MACE-3");
12769       caps = gst_caps_new_simple ("audio/x-mace",
12770           "maceversion", G_TYPE_INT, 3, NULL);
12771       break;
12772     case FOURCC_MAC6:
12773       _codec ("MACE-6");
12774       caps = gst_caps_new_simple ("audio/x-mace",
12775           "maceversion", G_TYPE_INT, 6, NULL);
12776       break;
12777     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
12778       /* ogg/vorbis */
12779       caps = gst_caps_new_empty_simple ("application/ogg");
12780       break;
12781     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
12782       _codec ("DV audio");
12783       caps = gst_caps_new_empty_simple ("audio/x-dv");
12784       break;
12785     case FOURCC_mp4a:
12786       _codec ("MPEG-4 AAC audio");
12787       caps = gst_caps_new_simple ("audio/mpeg",
12788           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
12789           "stream-format", G_TYPE_STRING, "raw", NULL);
12790       break;
12791     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
12792       _codec ("QDesign Music");
12793       caps = gst_caps_new_empty_simple ("audio/x-qdm");
12794       break;
12795     case FOURCC_QDM2:
12796       _codec ("QDesign Music v.2");
12797       /* FIXME: QDesign music version 2 (no constant) */
12798       if (FALSE && data) {
12799         caps = gst_caps_new_simple ("audio/x-qdm2",
12800             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
12801             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
12802             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
12803       } else {
12804         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
12805       }
12806       break;
12807     case FOURCC_agsm:
12808       _codec ("GSM audio");
12809       caps = gst_caps_new_empty_simple ("audio/x-gsm");
12810       break;
12811     case FOURCC_samr:
12812       _codec ("AMR audio");
12813       caps = gst_caps_new_empty_simple ("audio/AMR");
12814       break;
12815     case FOURCC_sawb:
12816       _codec ("AMR-WB audio");
12817       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
12818       break;
12819     case FOURCC_ima4:
12820       _codec ("Quicktime IMA ADPCM");
12821       caps = gst_caps_new_simple ("audio/x-adpcm",
12822           "layout", G_TYPE_STRING, "quicktime", NULL);
12823       break;
12824     case FOURCC_alac:
12825       _codec ("Apple lossless audio");
12826       caps = gst_caps_new_empty_simple ("audio/x-alac");
12827       break;
12828     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
12829       _codec ("QualComm PureVoice");
12830       caps = gst_caps_from_string ("audio/qcelp");
12831       break;
12832     case FOURCC_wma_:
12833     case FOURCC_owma:
12834       _codec ("WMA");
12835       caps = gst_caps_new_empty_simple ("audio/x-wma");
12836       break;
12837     case FOURCC_opus:
12838       _codec ("Opus");
12839       caps = gst_caps_new_empty_simple ("audio/x-opus");
12840       break;
12841     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
12842     {
12843       guint32 flags = 0;
12844       guint32 depth = 0;
12845       guint32 width = 0;
12846       GstAudioFormat format;
12847       enum
12848       {
12849         FLAG_IS_FLOAT = 0x1,
12850         FLAG_IS_BIG_ENDIAN = 0x2,
12851         FLAG_IS_SIGNED = 0x4,
12852         FLAG_IS_PACKED = 0x8,
12853         FLAG_IS_ALIGNED_HIGH = 0x10,
12854         FLAG_IS_NON_INTERLEAVED = 0x20
12855       };
12856       _codec ("Raw LPCM audio");
12857
12858       if (data && len >= 56) {
12859         depth = QT_UINT32 (data + 40);
12860         flags = QT_UINT32 (data + 44);
12861         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
12862       }
12863       if ((flags & FLAG_IS_FLOAT) == 0) {
12864         if (depth == 0)
12865           depth = 16;
12866         if (width == 0)
12867           width = 16;
12868         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
12869             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
12870             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
12871         caps = gst_caps_new_simple ("audio/x-raw",
12872             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12873             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12874             "non-interleaved" : "interleaved", NULL);
12875       } else {
12876         if (width == 0)
12877           width = 32;
12878         if (width == 64) {
12879           if (flags & FLAG_IS_BIG_ENDIAN)
12880             format = GST_AUDIO_FORMAT_F64BE;
12881           else
12882             format = GST_AUDIO_FORMAT_F64LE;
12883         } else {
12884           if (flags & FLAG_IS_BIG_ENDIAN)
12885             format = GST_AUDIO_FORMAT_F32BE;
12886           else
12887             format = GST_AUDIO_FORMAT_F32LE;
12888         }
12889         caps = gst_caps_new_simple ("audio/x-raw",
12890             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12891             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12892             "non-interleaved" : "interleaved", NULL);
12893       }
12894       break;
12895     }
12896     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
12897       /* ? */
12898     default:
12899     {
12900       char *s, fourstr[5];
12901
12902       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12903       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
12904       caps = gst_caps_new_empty_simple (s);
12905       g_free (s);
12906       break;
12907     }
12908   }
12909
12910   if (caps) {
12911     GstCaps *templ_caps =
12912         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
12913     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
12914     gst_caps_unref (caps);
12915     gst_caps_unref (templ_caps);
12916     caps = intersection;
12917   }
12918
12919   /* enable clipping for raw audio streams */
12920   s = gst_caps_get_structure (caps, 0);
12921   name = gst_structure_get_name (s);
12922   if (g_str_has_prefix (name, "audio/x-raw")) {
12923     stream->need_clip = TRUE;
12924     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
12925     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
12926   }
12927   return caps;
12928 }
12929
12930 static GstCaps *
12931 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12932     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12933 {
12934   GstCaps *caps;
12935
12936   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12937
12938   switch (fourcc) {
12939     case FOURCC_mp4s:
12940       _codec ("DVD subtitle");
12941       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
12942       stream->need_process = TRUE;
12943       break;
12944     case FOURCC_text:
12945       _codec ("Quicktime timed text");
12946       goto text;
12947     case FOURCC_tx3g:
12948       _codec ("3GPP timed text");
12949     text:
12950       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
12951           "utf8", NULL);
12952       /* actual text piece needs to be extracted */
12953       stream->need_process = TRUE;
12954       break;
12955     case FOURCC_stpp:
12956       _codec ("XML subtitles");
12957       caps = gst_caps_new_empty_simple ("application/ttml+xml");
12958       break;
12959     default:
12960     {
12961       char *s, fourstr[5];
12962
12963       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12964       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
12965       caps = gst_caps_new_empty_simple (s);
12966       g_free (s);
12967       break;
12968     }
12969   }
12970   return caps;
12971 }
12972
12973 static GstCaps *
12974 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12975     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12976 {
12977   GstCaps *caps;
12978
12979   switch (fourcc) {
12980     case FOURCC_m1v:
12981       _codec ("MPEG 1 video");
12982       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12983           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12984       break;
12985     default:
12986       caps = NULL;
12987       break;
12988   }
12989   return caps;
12990 }
12991
12992 static void
12993 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
12994     const gchar * system_id)
12995 {
12996   gint i;
12997
12998   if (!qtdemux->protection_system_ids)
12999     qtdemux->protection_system_ids =
13000         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
13001   /* Check whether we already have an entry for this system ID. */
13002   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
13003     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
13004     if (g_ascii_strcasecmp (system_id, id) == 0) {
13005       return;
13006     }
13007   }
13008   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
13009   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
13010           -1));
13011 }