d4fb29204b0fc41e0c40ee13ffa3f16e21584d9b
[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  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * 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
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
98
99 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
100
101 GST_DEBUG_CATEGORY (qtdemux_debug);
102
103 typedef struct _QtDemuxSegment QtDemuxSegment;
104 typedef struct _QtDemuxSample QtDemuxSample;
105
106 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
107
108 struct _QtDemuxSample
109 {
110   guint32 size;
111   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
112   guint64 offset;
113   guint64 timestamp;            /* DTS In mov time */
114   guint32 duration;             /* In mov time */
115   gboolean keyframe;            /* TRUE when this packet is a keyframe */
116 };
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calcuations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 /*
137  * Quicktime has tracks and segments. A track is a continuous piece of
138  * multimedia content. The track is not always played from start to finish but
139  * instead, pieces of the track are 'cut out' and played in sequence. This is
140  * what the segments do.
141  *
142  * Inside the track we have keyframes (K) and delta frames. The track has its
143  * own timing, which starts from 0 and extends to end. The position in the track
144  * is called the media_time.
145  *
146  * The segments now describe the pieces that should be played from this track
147  * and are basically tuples of media_time/duration/rate entries. We can have
148  * multiple segments and they are all played after one another. An example:
149  *
150  * segment 1: media_time: 1 second, duration: 1 second, rate 1
151  * segment 2: media_time: 3 second, duration: 2 second, rate 2
152  *
153  * To correctly play back this track, one must play: 1 second of media starting
154  * from media_time 1 followed by 2 seconds of media starting from media_time 3
155  * at a rate of 2.
156  *
157  * Each of the segments will be played at a specific time, the first segment at
158  * time 0, the second one after the duration of the first one, etc.. Note that
159  * the time in resulting playback is not identical to the media_time of the
160  * track anymore.
161  *
162  * Visually, assuming the track has 4 second of media_time:
163  *
164  *                (a)                   (b)          (c)              (d)
165  *         .-----------------------------------------------------------.
166  * track:  | K.....K.........K........K.......K.......K...........K... |
167  *         '-----------------------------------------------------------'
168  *         0              1              2              3              4
169  *           .------------^              ^   .----------^              ^
170  *          /              .-------------'  /       .------------------'
171  *         /              /          .-----'       /
172  *         .--------------.         .--------------.
173  *         | segment 1    |         | segment 2    |
174  *         '--------------'         '--------------'
175  *
176  * The challenge here is to cut out the right pieces of the track for each of
177  * the playback segments. This fortunately can easily be done with the SEGMENT
178  * events of GStreamer.
179  *
180  * For playback of segment 1, we need to provide the decoder with the keyframe
181  * (a), in the above figure, but we must instruct it only to output the decoded
182  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
183  * position set to the time of the segment: 0.
184  *
185  * We then proceed to push data from keyframe (a) to frame (b). The decoder
186  * decodes but clips all before media_time 1.
187  *
188  * After finishing a segment, we push out a new SEGMENT event with the clipping
189  * boundaries of the new data.
190  *
191  * This is a good usecase for the GStreamer accumulated SEGMENT events.
192  */
193
194 struct _QtDemuxSegment
195 {
196   /* global time and duration, all gst time */
197   GstClockTime time;
198   GstClockTime stop_time;
199   GstClockTime duration;
200   /* media time of trak, all gst time */
201   GstClockTime media_start;
202   GstClockTime media_stop;
203   gdouble rate;
204   /* Media start time in trak timescale units */
205   guint32 trak_media_start;
206 };
207
208 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
209
210 /* Used with fragmented MP4 files (mfra atom) */
211 typedef struct
212 {
213   GstClockTime ts;
214   guint64 moof_offset;
215 } QtDemuxRandomAccessEntry;
216
217 struct _QtDemuxStream
218 {
219   GstPad *pad;
220
221   /* stream type */
222   guint32 subtype;
223   GstCaps *caps;
224   guint32 fourcc;
225   gboolean sparse;
226
227   gboolean new_caps;            /* If TRUE, caps need to be generated (by
228                                  * calling _configure_stream()) This happens
229                                  * for MSS and fragmented streams */
230
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 units */
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 */
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   guint64 duration_last_moof;
260
261   guint32 offset_in_sample;     /* Offset in the current sample, used for
262                                  * streams which have got exceedingly big
263                                  * sample size (such as 24s of raw audio).
264                                  * Only used when max_buffer_size is non-NULL */
265   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
266                                  * Currently only set for raw audio streams*/
267
268   /* if we use chunks or samples */
269   gboolean sampled;
270   guint padding;
271
272   /* video info */
273   gint width;
274   gint height;
275   /* aspect ratio */
276   gint display_width;
277   gint display_height;
278   gint par_w;
279   gint par_h;
280   /* Numerator/denominator framerate */
281   gint fps_n;
282   gint fps_d;
283   GstVideoColorimetry colorimetry;
284   guint16 bits_per_sample;
285   guint16 color_table_id;
286   GstMemory *rgb8_palette;
287   guint interlace_mode;
288   guint field_order;
289
290   /* audio info */
291   gdouble rate;
292   gint n_channels;
293   guint samples_per_packet;
294   guint samples_per_frame;
295   guint bytes_per_packet;
296   guint bytes_per_sample;
297   guint bytes_per_frame;
298   guint compression;
299
300   /* allocation */
301   gboolean use_allocator;
302   GstAllocator *allocator;
303   GstAllocationParams params;
304
305   gsize alignment;
306
307   /* when a discontinuity is pending */
308   gboolean discont;
309
310   /* list of buffers to push first */
311   GSList *buffers;
312
313   /* if we need to clip this buffer. This is only needed for uncompressed
314    * data */
315   gboolean need_clip;
316
317   /* buffer needs some custom processing, e.g. subtitles */
318   gboolean need_process;
319
320   /* current position */
321   guint32 segment_index;
322   guint32 sample_index;
323   GstClockTime time_position;   /* in gst time */
324   guint64 accumulated_base;
325
326   /* the Gst segment we are processing out, used for clipping */
327   GstSegment segment;
328
329   /* quicktime segments */
330   guint32 n_segments;
331   QtDemuxSegment *segments;
332   gboolean dummy_segment;
333   guint32 from_sample;
334   guint32 to_sample;
335
336   gboolean sent_eos;
337   GstTagList *pending_tags;
338   gboolean send_global_tags;
339
340   GstEvent *pending_event;
341
342   GstByteReader stco;
343   GstByteReader stsz;
344   GstByteReader stsc;
345   GstByteReader stts;
346   GstByteReader stss;
347   GstByteReader stps;
348   GstByteReader ctts;
349
350   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
351   gint64 stbl_index;
352   /* stco */
353   guint co_size;
354   GstByteReader co_chunk;
355   guint32 first_chunk;
356   guint32 current_chunk;
357   guint32 last_chunk;
358   guint32 samples_per_chunk;
359   guint32 stco_sample_index;
360   /* stsz */
361   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
362   /* stsc */
363   guint32 stsc_index;
364   guint32 n_samples_per_chunk;
365   guint32 stsc_chunk_index;
366   guint32 stsc_sample_index;
367   guint64 chunk_offset;
368   /* stts */
369   guint32 stts_index;
370   guint32 stts_samples;
371   guint32 n_sample_times;
372   guint32 stts_sample_index;
373   guint64 stts_time;
374   guint32 stts_duration;
375   /* stss */
376   gboolean stss_present;
377   guint32 n_sample_syncs;
378   guint32 stss_index;
379   /* stps */
380   gboolean stps_present;
381   guint32 n_sample_partial_syncs;
382   guint32 stps_index;
383   QtDemuxRandomAccessEntry *ra_entries;
384   guint n_ra_entries;
385
386   const QtDemuxRandomAccessEntry *pending_seek;
387
388   /* ctts */
389   gboolean ctts_present;
390   guint32 n_composition_times;
391   guint32 ctts_index;
392   guint32 ctts_sample_index;
393   guint32 ctts_count;
394   gint32 ctts_soffset;
395
396   /* cslg */
397   guint32 cslg_shift;
398
399   /* fragmented */
400   gboolean parsed_trex;
401   guint32 def_sample_duration;
402   guint32 def_sample_size;
403   guint32 def_sample_flags;
404
405   gboolean disabled;
406
407   /* stereoscopic video streams */
408   GstVideoMultiviewMode multiview_mode;
409   GstVideoMultiviewFlags multiview_flags;
410
411   /* protected streams */
412   gboolean protected;
413   guint32 protection_scheme_type;
414   guint32 protection_scheme_version;
415   gpointer protection_scheme_info;      /* specific to the protection scheme */
416   GQueue protection_scheme_event_queue;
417 };
418
419 /* Contains properties and cryptographic info for a set of samples from a
420  * track protected using Common Encryption (cenc) */
421 struct _QtDemuxCencSampleSetInfo
422 {
423   GstStructure *default_properties;
424
425   /* @crypto_info holds one GstStructure per sample */
426   GPtrArray *crypto_info;
427 };
428
429 static const gchar *
430 qt_demux_state_string (enum QtDemuxState state)
431 {
432   switch (state) {
433     case QTDEMUX_STATE_INITIAL:
434       return "<INITIAL>";
435     case QTDEMUX_STATE_HEADER:
436       return "<HEADER>";
437     case QTDEMUX_STATE_MOVIE:
438       return "<MOVIE>";
439     case QTDEMUX_STATE_BUFFER_MDAT:
440       return "<BUFFER_MDAT>";
441     default:
442       return "<UNKNOWN>";
443   }
444 }
445
446 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
447 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
448     guint32 fourcc, GstByteReader * parser);
449 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
450 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
451     guint32 fourcc, GstByteReader * parser);
452
453 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
454
455 static GstStaticPadTemplate gst_qtdemux_sink_template =
456     GST_STATIC_PAD_TEMPLATE ("sink",
457     GST_PAD_SINK,
458     GST_PAD_ALWAYS,
459     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
460         "application/x-3gp")
461     );
462
463 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
464 GST_STATIC_PAD_TEMPLATE ("video_%u",
465     GST_PAD_SRC,
466     GST_PAD_SOMETIMES,
467     GST_STATIC_CAPS_ANY);
468
469 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
470 GST_STATIC_PAD_TEMPLATE ("audio_%u",
471     GST_PAD_SRC,
472     GST_PAD_SOMETIMES,
473     GST_STATIC_CAPS_ANY);
474
475 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
476 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
477     GST_PAD_SRC,
478     GST_PAD_SOMETIMES,
479     GST_STATIC_CAPS_ANY);
480
481 #define gst_qtdemux_parent_class parent_class
482 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
483
484 static void gst_qtdemux_dispose (GObject * object);
485
486 static guint32
487 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
488     GstClockTime media_time);
489 static guint32
490 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
491     QtDemuxStream * str, gint64 media_offset);
492
493 #if 0
494 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
495 static GstIndex *gst_qtdemux_get_index (GstElement * element);
496 #endif
497 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
498     GstStateChange transition);
499 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
500 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
501     GstObject * parent, GstPadMode mode, gboolean active);
502
503 static void gst_qtdemux_loop (GstPad * pad);
504 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
505     GstBuffer * inbuf);
506 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
507     GstEvent * event);
508 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
509 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
510     QtDemuxStream * stream);
511 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
512     gboolean force);
513
514 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
515     const guint8 * buffer, guint length);
516 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
517     const guint8 * buffer, guint length);
518 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
519 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
520     GNode * udta);
521
522 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
523     QtDemuxStream * stream, GNode * esds, GstTagList * list);
524 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
525     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
526     gchar ** codec_name);
527 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
528     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
529     gchar ** codec_name);
530 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
531     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
532     gchar ** codec_name);
533 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
534     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
535     gchar ** codec_name);
536
537 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
538     QtDemuxStream * stream, guint32 n);
539 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
540 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
541     QtDemuxStream * stream);
542 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
543     QtDemuxStream * stream);
544 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
545 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
546 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
547     QtDemuxStream * stream);
548 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
549     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
550 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
551     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
552     GstClockTime * _start, GstClockTime * _stop);
553 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
554     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
555
556 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
557 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
558
559 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
560
561 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
562     QtDemuxStream * stream, guint sample_index);
563 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
564     const gchar * id);
565 static void qtdemux_gst_structure_free (GstStructure * gststructure);
566
567 static void
568 gst_qtdemux_class_init (GstQTDemuxClass * klass)
569 {
570   GObjectClass *gobject_class;
571   GstElementClass *gstelement_class;
572
573   gobject_class = (GObjectClass *) klass;
574   gstelement_class = (GstElementClass *) klass;
575
576   parent_class = g_type_class_peek_parent (klass);
577
578   gobject_class->dispose = gst_qtdemux_dispose;
579
580   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
581 #if 0
582   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
583   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
584 #endif
585
586   gst_tag_register_musicbrainz_tags ();
587
588   gst_element_class_add_static_pad_template (gstelement_class,
589       &gst_qtdemux_sink_template);
590   gst_element_class_add_static_pad_template (gstelement_class,
591       &gst_qtdemux_videosrc_template);
592   gst_element_class_add_static_pad_template (gstelement_class,
593       &gst_qtdemux_audiosrc_template);
594   gst_element_class_add_static_pad_template (gstelement_class,
595       &gst_qtdemux_subsrc_template);
596   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
597       "Codec/Demuxer",
598       "Demultiplex a QuickTime file into audio and video streams",
599       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
600
601   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
602
603 }
604
605 static void
606 gst_qtdemux_init (GstQTDemux * qtdemux)
607 {
608   qtdemux->sinkpad =
609       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
610   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
611   gst_pad_set_activatemode_function (qtdemux->sinkpad,
612       qtdemux_sink_activate_mode);
613   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
614   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
615   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
616
617   qtdemux->state = QTDEMUX_STATE_INITIAL;
618   qtdemux->pullbased = FALSE;
619   qtdemux->posted_redirect = FALSE;
620   qtdemux->neededbytes = 16;
621   qtdemux->todrop = 0;
622   qtdemux->adapter = gst_adapter_new ();
623   qtdemux->offset = 0;
624   qtdemux->first_mdat = -1;
625   qtdemux->got_moov = FALSE;
626   qtdemux->mdatoffset = -1;
627   qtdemux->mdatbuffer = NULL;
628   qtdemux->restoredata_buffer = NULL;
629   qtdemux->restoredata_offset = -1;
630   qtdemux->fragment_start = -1;
631   qtdemux->fragment_start_offset = -1;
632   qtdemux->media_caps = NULL;
633   qtdemux->exposed = FALSE;
634   qtdemux->mss_mode = FALSE;
635   qtdemux->pending_newsegment = NULL;
636   qtdemux->upstream_format_is_time = FALSE;
637   qtdemux->have_group_id = FALSE;
638   qtdemux->group_id = G_MAXUINT;
639   qtdemux->cenc_aux_info_offset = 0;
640   qtdemux->cenc_aux_info_sizes = NULL;
641   qtdemux->cenc_aux_sample_count = 0;
642   qtdemux->protection_system_ids = NULL;
643   g_queue_init (&qtdemux->protection_event_queue);
644   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
645   qtdemux->flowcombiner = gst_flow_combiner_new ();
646
647   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
648 }
649
650 static void
651 gst_qtdemux_dispose (GObject * object)
652 {
653   GstQTDemux *qtdemux = GST_QTDEMUX (object);
654
655   if (qtdemux->adapter) {
656     g_object_unref (G_OBJECT (qtdemux->adapter));
657     qtdemux->adapter = NULL;
658   }
659   gst_flow_combiner_free (qtdemux->flowcombiner);
660   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
661       NULL);
662   g_queue_clear (&qtdemux->protection_event_queue);
663
664   g_free (qtdemux->cenc_aux_info_sizes);
665   qtdemux->cenc_aux_info_sizes = NULL;
666
667   G_OBJECT_CLASS (parent_class)->dispose (object);
668 }
669
670 static void
671 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
672 {
673   if (qtdemux->posted_redirect) {
674     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
675         (_("This file contains no playable streams.")),
676         ("no known streams found, a redirect message has been posted"));
677   } else {
678     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
679         (_("This file contains no playable streams.")),
680         ("no known streams found"));
681   }
682 }
683
684 static GstBuffer *
685 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
686 {
687   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
688       mem, size, 0, size, mem, free_func);
689 }
690
691 static GstFlowReturn
692 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
693     GstBuffer ** buf)
694 {
695   GstFlowReturn flow;
696   GstMapInfo map;
697   gsize bsize;
698
699   if (G_UNLIKELY (size == 0)) {
700     GstFlowReturn ret;
701     GstBuffer *tmp = NULL;
702
703     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
704     if (ret != GST_FLOW_OK)
705       return ret;
706
707     gst_buffer_map (tmp, &map, GST_MAP_READ);
708     size = QT_UINT32 (map.data);
709     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
710
711     gst_buffer_unmap (tmp, &map);
712     gst_buffer_unref (tmp);
713   }
714
715   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
716   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
717     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
718       /* we're pulling header but already got most interesting bits,
719        * so never mind the rest (e.g. tags) (that much) */
720       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
721           size);
722       return GST_FLOW_EOS;
723     } else {
724       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
725           (_("This file is invalid and cannot be played.")),
726           ("atom has bogus size %" G_GUINT64_FORMAT, size));
727       return GST_FLOW_ERROR;
728     }
729   }
730
731   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
732
733   if (G_UNLIKELY (flow != GST_FLOW_OK))
734     return flow;
735
736   bsize = gst_buffer_get_size (*buf);
737   /* Catch short reads - we don't want any partial atoms */
738   if (G_UNLIKELY (bsize < size)) {
739     GST_WARNING_OBJECT (qtdemux,
740         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
741     gst_buffer_unref (*buf);
742     *buf = NULL;
743     return GST_FLOW_EOS;
744   }
745
746   return flow;
747 }
748
749 #if 1
750 static gboolean
751 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
752     GstFormat src_format, gint64 src_value, GstFormat dest_format,
753     gint64 * dest_value)
754 {
755   gboolean res = TRUE;
756   QtDemuxStream *stream = gst_pad_get_element_private (pad);
757   gint32 index;
758
759   if (stream->subtype != FOURCC_vide) {
760     res = FALSE;
761     goto done;
762   }
763
764   switch (src_format) {
765     case GST_FORMAT_TIME:
766       switch (dest_format) {
767         case GST_FORMAT_BYTES:{
768           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
769           if (-1 == index) {
770             res = FALSE;
771             goto done;
772           }
773
774           *dest_value = stream->samples[index].offset;
775
776           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
777               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
778               GST_TIME_ARGS (src_value), *dest_value);
779           break;
780         }
781         default:
782           res = FALSE;
783           break;
784       }
785       break;
786     case GST_FORMAT_BYTES:
787       switch (dest_format) {
788         case GST_FORMAT_TIME:{
789           index =
790               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
791               stream, src_value);
792
793           if (-1 == index) {
794             res = FALSE;
795             goto done;
796           }
797
798           *dest_value =
799               QTSTREAMTIME_TO_GSTTIME (stream,
800               stream->samples[index].timestamp);
801           GST_DEBUG_OBJECT (qtdemux,
802               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
803               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
804           break;
805         }
806         default:
807           res = FALSE;
808           break;
809       }
810       break;
811     default:
812       res = FALSE;
813       break;
814   }
815
816 done:
817   return res;
818 }
819 #endif
820
821 static gboolean
822 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
823 {
824   gboolean res = FALSE;
825
826   *duration = GST_CLOCK_TIME_NONE;
827
828   if (qtdemux->duration != 0 &&
829       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
830     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
831     res = TRUE;
832   } else {
833     *duration = GST_CLOCK_TIME_NONE;
834   }
835
836   return res;
837 }
838
839 static gboolean
840 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
841     GstQuery * query)
842 {
843   gboolean res = FALSE;
844   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
845
846   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
847
848   switch (GST_QUERY_TYPE (query)) {
849     case GST_QUERY_POSITION:{
850       GstFormat fmt;
851
852       gst_query_parse_position (query, &fmt, NULL);
853       if (fmt == GST_FORMAT_TIME
854           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
855         gst_query_set_position (query, GST_FORMAT_TIME,
856             qtdemux->segment.position);
857         res = TRUE;
858       }
859     }
860       break;
861     case GST_QUERY_DURATION:{
862       GstFormat fmt;
863
864       gst_query_parse_duration (query, &fmt, NULL);
865       if (fmt == GST_FORMAT_TIME) {
866         /* First try to query upstream */
867         res = gst_pad_query_default (pad, parent, query);
868         if (!res) {
869           GstClockTime duration;
870           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
871             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
872             res = TRUE;
873           }
874         }
875       }
876       break;
877     }
878     case GST_QUERY_CONVERT:{
879       GstFormat src_fmt, dest_fmt;
880       gint64 src_value, dest_value = 0;
881
882       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
883
884       res = gst_qtdemux_src_convert (qtdemux, pad,
885           src_fmt, src_value, dest_fmt, &dest_value);
886       if (res) {
887         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
888         res = TRUE;
889       }
890       break;
891     }
892     case GST_QUERY_FORMATS:
893       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
894       res = TRUE;
895       break;
896     case GST_QUERY_SEEKING:{
897       GstFormat fmt;
898       gboolean seekable;
899
900       /* try upstream first */
901       res = gst_pad_query_default (pad, parent, query);
902
903       if (!res) {
904         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
905         if (fmt == GST_FORMAT_TIME) {
906           GstClockTime duration;
907
908           gst_qtdemux_get_duration (qtdemux, &duration);
909           seekable = TRUE;
910           if (!qtdemux->pullbased) {
911             GstQuery *q;
912
913             /* we might be able with help from upstream */
914             seekable = FALSE;
915             q = gst_query_new_seeking (GST_FORMAT_BYTES);
916             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
917               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
918               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
919             }
920             gst_query_unref (q);
921           }
922           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
923           res = TRUE;
924         }
925       }
926       break;
927     }
928     case GST_QUERY_SEGMENT:
929     {
930       GstFormat format;
931       gint64 start, stop;
932
933       format = qtdemux->segment.format;
934
935       start =
936           gst_segment_to_stream_time (&qtdemux->segment, format,
937           qtdemux->segment.start);
938       if ((stop = qtdemux->segment.stop) == -1)
939         stop = qtdemux->segment.duration;
940       else
941         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
942
943       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
944       res = TRUE;
945       break;
946     }
947     default:
948       res = gst_pad_query_default (pad, parent, query);
949       break;
950   }
951
952   return res;
953 }
954
955 static void
956 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
957 {
958   if (G_LIKELY (stream->pad)) {
959     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
960         GST_DEBUG_PAD_NAME (stream->pad));
961
962     if (G_UNLIKELY (stream->pending_tags)) {
963       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
964           stream->pending_tags);
965       gst_pad_push_event (stream->pad,
966           gst_event_new_tag (stream->pending_tags));
967       stream->pending_tags = NULL;
968     }
969
970     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
971       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
972           qtdemux->tag_list);
973       gst_pad_push_event (stream->pad,
974           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
975       stream->send_global_tags = FALSE;
976     }
977   }
978 }
979
980 /* push event on all source pads; takes ownership of the event */
981 static void
982 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
983 {
984   guint n;
985   gboolean has_valid_stream = FALSE;
986   GstEventType etype = GST_EVENT_TYPE (event);
987
988   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
989       GST_EVENT_TYPE_NAME (event));
990
991   for (n = 0; n < qtdemux->n_streams; n++) {
992     GstPad *pad;
993     QtDemuxStream *stream = qtdemux->streams[n];
994     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
995
996     if ((pad = stream->pad)) {
997       has_valid_stream = TRUE;
998
999       if (etype == GST_EVENT_EOS) {
1000         /* let's not send twice */
1001         if (stream->sent_eos)
1002           continue;
1003         stream->sent_eos = TRUE;
1004       }
1005
1006       gst_pad_push_event (pad, gst_event_ref (event));
1007     }
1008   }
1009
1010   gst_event_unref (event);
1011
1012   /* if it is EOS and there are no pads, post an error */
1013   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1014     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1015   }
1016 }
1017
1018 /* push a pending newsegment event, if any from the streaming thread */
1019 static void
1020 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1021 {
1022   if (qtdemux->pending_newsegment) {
1023     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1024     qtdemux->pending_newsegment = NULL;
1025   }
1026 }
1027
1028 typedef struct
1029 {
1030   guint64 media_time;
1031 } FindData;
1032
1033 static gint
1034 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1035 {
1036   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1037     return 1;
1038   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1039     return 0;
1040
1041   return -1;
1042 }
1043
1044 /* find the index of the sample that includes the data for @media_time using a
1045  * binary search.  Only to be called in optimized cases of linear search below.
1046  *
1047  * Returns the index of the sample.
1048  */
1049 static guint32
1050 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1051     guint64 media_time)
1052 {
1053   QtDemuxSample *result;
1054   guint32 index;
1055
1056   /* convert media_time to mov format */
1057   media_time =
1058       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1059
1060   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1061       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1062       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1063
1064   if (G_LIKELY (result))
1065     index = result - str->samples;
1066   else
1067     index = 0;
1068
1069   return index;
1070 }
1071
1072
1073
1074 /* find the index of the sample that includes the data for @media_offset using a
1075  * linear search
1076  *
1077  * Returns the index of the sample.
1078  */
1079 static guint32
1080 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1081     QtDemuxStream * str, gint64 media_offset)
1082 {
1083   QtDemuxSample *result = str->samples;
1084   guint32 index = 0;
1085
1086   if (result == NULL || str->n_samples == 0)
1087     return -1;
1088
1089   if (media_offset == result->offset)
1090     return index;
1091
1092   result++;
1093   while (index < str->n_samples - 1) {
1094     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1095       goto parse_failed;
1096
1097     if (media_offset < result->offset)
1098       break;
1099
1100     index++;
1101     result++;
1102   }
1103   return index;
1104
1105   /* ERRORS */
1106 parse_failed:
1107   {
1108     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1109     return -1;
1110   }
1111 }
1112
1113 /* find the index of the sample that includes the data for @media_time using a
1114  * linear search, and keeping in mind that not all samples may have been parsed
1115  * yet.  If possible, it will delegate to binary search.
1116  *
1117  * Returns the index of the sample.
1118  */
1119 static guint32
1120 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1121     GstClockTime media_time)
1122 {
1123   guint32 index = 0;
1124   guint64 mov_time;
1125   QtDemuxSample *sample;
1126
1127   /* convert media_time to mov format */
1128   mov_time =
1129       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1130
1131   sample = str->samples;
1132   if (mov_time == sample->timestamp + sample->pts_offset)
1133     return index;
1134
1135   /* use faster search if requested time in already parsed range */
1136   sample = str->samples + str->stbl_index;
1137   if (str->stbl_index >= 0 &&
1138       mov_time <= (sample->timestamp + sample->pts_offset))
1139     return gst_qtdemux_find_index (qtdemux, str, media_time);
1140
1141   while (index < str->n_samples - 1) {
1142     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1143       goto parse_failed;
1144
1145     sample = str->samples + index + 1;
1146     if (mov_time < (sample->timestamp + sample->pts_offset))
1147       break;
1148
1149     index++;
1150   }
1151   return index;
1152
1153   /* ERRORS */
1154 parse_failed:
1155   {
1156     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1157     return -1;
1158   }
1159 }
1160
1161 /* find the index of the keyframe needed to decode the sample at @index
1162  * of stream @str, or of a subsequent keyframe (depending on @next)
1163  *
1164  * Returns the index of the keyframe.
1165  */
1166 static guint32
1167 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1168     guint32 index, gboolean next)
1169 {
1170   guint32 new_index = index;
1171
1172   if (index >= str->n_samples) {
1173     new_index = str->n_samples;
1174     goto beach;
1175   }
1176
1177   /* all keyframes, return index */
1178   if (str->all_keyframe) {
1179     new_index = index;
1180     goto beach;
1181   }
1182
1183   /* else search until we have a keyframe */
1184   while (new_index < str->n_samples) {
1185     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1186       goto parse_failed;
1187
1188     if (str->samples[new_index].keyframe)
1189       break;
1190
1191     if (new_index == 0)
1192       break;
1193
1194     if (next)
1195       new_index++;
1196     else
1197       new_index--;
1198   }
1199
1200   if (new_index == str->n_samples) {
1201     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1202     new_index = -1;
1203   }
1204
1205 beach:
1206   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1207       "gave %u", next ? "after" : "before", index, new_index);
1208
1209   return new_index;
1210
1211   /* ERRORS */
1212 parse_failed:
1213   {
1214     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1215     return -1;
1216   }
1217 }
1218
1219 /* find the segment for @time_position for @stream
1220  *
1221  * Returns the index of the segment containing @time_position.
1222  * Returns the last segment and sets the @eos variable to TRUE
1223  * if the time is beyond the end. @eos may be NULL
1224  */
1225 static guint32
1226 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1227     GstClockTime time_position)
1228 {
1229   gint i;
1230   guint32 seg_idx;
1231
1232   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1233       GST_TIME_ARGS (time_position));
1234
1235   seg_idx = -1;
1236   for (i = 0; i < stream->n_segments; i++) {
1237     QtDemuxSegment *segment = &stream->segments[i];
1238
1239     GST_LOG_OBJECT (stream->pad,
1240         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1241         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1242
1243     /* For the last segment we include stop_time in the last segment */
1244     if (i < stream->n_segments - 1) {
1245       if (segment->time <= time_position && time_position < segment->stop_time) {
1246         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1247         seg_idx = i;
1248         break;
1249       }
1250     } else {
1251       /* Last segment always matches */
1252       seg_idx = i;
1253       break;
1254     }
1255   }
1256   return seg_idx;
1257 }
1258
1259 /* move the stream @str to the sample position @index.
1260  *
1261  * Updates @str->sample_index and marks discontinuity if needed.
1262  */
1263 static void
1264 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1265     guint32 index)
1266 {
1267   /* no change needed */
1268   if (index == str->sample_index)
1269     return;
1270
1271   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1272       str->n_samples);
1273
1274   /* position changed, we have a discont */
1275   str->sample_index = index;
1276   str->offset_in_sample = 0;
1277   /* Each time we move in the stream we store the position where we are
1278    * starting from */
1279   str->from_sample = index;
1280   str->discont = TRUE;
1281 }
1282
1283 static void
1284 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1285     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1286 {
1287   guint64 min_offset;
1288   gint64 min_byte_offset = -1;
1289   gint n;
1290
1291   min_offset = desired_time;
1292
1293   /* for each stream, find the index of the sample in the segment
1294    * and move back to the previous keyframe. */
1295   for (n = 0; n < qtdemux->n_streams; n++) {
1296     QtDemuxStream *str;
1297     guint32 index;
1298     guint32 seg_idx;
1299     GstClockTime media_start;
1300     GstClockTime media_time;
1301     GstClockTime seg_time;
1302     QtDemuxSegment *seg;
1303     gboolean empty_segment = FALSE;
1304
1305     str = qtdemux->streams[n];
1306
1307     if (str->sparse && !use_sparse)
1308       continue;
1309
1310     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1311     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1312
1313     /* get segment and time in the segment */
1314     seg = &str->segments[seg_idx];
1315     seg_time = (desired_time - seg->time) * seg->rate;
1316
1317     while (QTSEGMENT_IS_EMPTY (seg)) {
1318       seg_time = 0;
1319       empty_segment = TRUE;
1320       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1321           seg_idx);
1322       seg_idx++;
1323       if (seg_idx == str->n_segments)
1324         break;
1325       seg = &str->segments[seg_idx];
1326     }
1327
1328     if (seg_idx == str->n_segments) {
1329       /* FIXME track shouldn't have the last segment as empty, but if it
1330        * happens we better handle it */
1331       continue;
1332     }
1333
1334     /* get the media time in the segment */
1335     media_start = seg->media_start + seg_time;
1336
1337     /* get the index of the sample with media time */
1338     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1339     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1340         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1341         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1342         empty_segment);
1343
1344     /* shift to next frame if we are looking for next keyframe */
1345     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1346         && index < str->stbl_index)
1347       index++;
1348
1349     if (!empty_segment) {
1350       /* find previous keyframe */
1351       index = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1352
1353       /* we will settle for one before if none found after */
1354       if (next && index == -1)
1355         index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1356
1357       /* Snap to the start ts of the keyframe we found */
1358
1359       /* get timestamp of keyframe */
1360       media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]);
1361       GST_DEBUG_OBJECT (qtdemux,
1362           "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1363           G_GUINT64_FORMAT, index, GST_TIME_ARGS (media_time),
1364           str->samples[index].offset);
1365
1366       /* keyframes in the segment get a chance to change the
1367        * desired_offset. keyframes out of the segment are
1368        * ignored. */
1369       if (media_time >= seg->media_start) {
1370         GstClockTime seg_time;
1371
1372         /* this keyframe is inside the segment, convert back to
1373          * segment time */
1374         seg_time = (media_time - seg->media_start) + seg->time;
1375         if ((!next && (seg_time < min_offset)) ||
1376             (next && (seg_time > min_offset)))
1377           min_offset = seg_time;
1378       }
1379     }
1380
1381     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1382       min_byte_offset = str->samples[index].offset;
1383   }
1384
1385   if (key_time)
1386     *key_time = min_offset;
1387   if (key_offset)
1388     *key_offset = min_byte_offset;
1389 }
1390
1391 static gboolean
1392 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1393     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1394 {
1395   gboolean res;
1396
1397   g_return_val_if_fail (format != NULL, FALSE);
1398   g_return_val_if_fail (cur != NULL, FALSE);
1399   g_return_val_if_fail (stop != NULL, FALSE);
1400
1401   if (*format == GST_FORMAT_TIME)
1402     return TRUE;
1403
1404   res = TRUE;
1405   if (cur_type != GST_SEEK_TYPE_NONE)
1406     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1407   if (res && stop_type != GST_SEEK_TYPE_NONE)
1408     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1409
1410   if (res)
1411     *format = GST_FORMAT_TIME;
1412
1413   return res;
1414 }
1415
1416 /* perform seek in push based mode:
1417    find BYTE position to move to based on time and delegate to upstream
1418 */
1419 static gboolean
1420 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1421 {
1422   gdouble rate;
1423   GstFormat format;
1424   GstSeekFlags flags;
1425   GstSeekType cur_type, stop_type;
1426   gint64 cur, stop, key_cur;
1427   gboolean res;
1428   gint64 byte_cur;
1429   gint64 original_stop;
1430   guint32 seqnum;
1431
1432   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1433
1434   gst_event_parse_seek (event, &rate, &format, &flags,
1435       &cur_type, &cur, &stop_type, &stop);
1436   seqnum = gst_event_get_seqnum (event);
1437
1438   /* only forward streaming and seeking is possible */
1439   if (rate <= 0)
1440     goto unsupported_seek;
1441
1442   /* convert to TIME if needed and possible */
1443   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1444           stop_type, &stop))
1445     goto no_format;
1446
1447   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1448    * the original stop position to use when upstream pushes the new segment
1449    * for this seek */
1450   original_stop = stop;
1451   stop = -1;
1452
1453   /* find reasonable corresponding BYTE position,
1454    * also try to mind about keyframes, since we can not go back a bit for them
1455    * later on */
1456   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1457    * mostly just work, but let's not yet boldly go there  ... */
1458   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1459
1460   if (byte_cur == -1)
1461     goto abort_seek;
1462
1463   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1464       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1465       stop);
1466
1467   GST_OBJECT_LOCK (qtdemux);
1468   qtdemux->seek_offset = byte_cur;
1469   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1470     qtdemux->push_seek_start = cur;
1471   } else {
1472     qtdemux->push_seek_start = key_cur;
1473   }
1474
1475   if (stop_type == GST_SEEK_TYPE_NONE) {
1476     qtdemux->push_seek_stop = qtdemux->segment.stop;
1477   } else {
1478     qtdemux->push_seek_stop = original_stop;
1479   }
1480   GST_OBJECT_UNLOCK (qtdemux);
1481
1482   /* BYTE seek event */
1483   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1484       stop_type, stop);
1485   gst_event_set_seqnum (event, seqnum);
1486   res = gst_pad_push_event (qtdemux->sinkpad, event);
1487
1488   return res;
1489
1490   /* ERRORS */
1491 abort_seek:
1492   {
1493     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1494         "seek aborted.");
1495     return FALSE;
1496   }
1497 unsupported_seek:
1498   {
1499     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1500     return FALSE;
1501   }
1502 no_format:
1503   {
1504     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1505     return FALSE;
1506   }
1507 }
1508
1509 /* perform the seek.
1510  *
1511  * We set all segment_indexes in the streams to unknown and
1512  * adjust the time_position to the desired position. this is enough
1513  * to trigger a segment switch in the streaming thread to start
1514  * streaming from the desired position.
1515  *
1516  * Keyframe seeking is a little more complicated when dealing with
1517  * segments. Ideally we want to move to the previous keyframe in
1518  * the segment but there might not be a keyframe in the segment. In
1519  * fact, none of the segments could contain a keyframe. We take a
1520  * practical approach: seek to the previous keyframe in the segment,
1521  * if there is none, seek to the beginning of the segment.
1522  *
1523  * Called with STREAM_LOCK
1524  */
1525 static gboolean
1526 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1527     guint32 seqnum, GstSeekFlags flags)
1528 {
1529   gint64 desired_offset;
1530   gint n;
1531
1532   desired_offset = segment->position;
1533
1534   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1535       GST_TIME_ARGS (desired_offset));
1536
1537   /* may not have enough fragmented info to do this adjustment,
1538    * and we can't scan (and probably should not) at this time with
1539    * possibly flushing upstream */
1540   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1541     gint64 min_offset;
1542     gboolean next, before, after;
1543
1544     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1545     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1546     next = after && !before;
1547     if (segment->rate < 0)
1548       next = !next;
1549
1550     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1551         NULL);
1552     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1553         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1554     desired_offset = min_offset;
1555   }
1556
1557   /* and set all streams to the final position */
1558   gst_flow_combiner_reset (qtdemux->flowcombiner);
1559   qtdemux->segment_seqnum = seqnum;
1560   for (n = 0; n < qtdemux->n_streams; n++) {
1561     QtDemuxStream *stream = qtdemux->streams[n];
1562
1563     stream->time_position = desired_offset;
1564     stream->accumulated_base = 0;
1565     stream->sample_index = -1;
1566     stream->offset_in_sample = 0;
1567     stream->segment_index = -1;
1568     stream->sent_eos = FALSE;
1569
1570     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1571       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1572   }
1573   segment->position = desired_offset;
1574   segment->time = desired_offset;
1575   if (segment->rate >= 0) {
1576     segment->start = desired_offset;
1577
1578     /* we stop at the end */
1579     if (segment->stop == -1)
1580       segment->stop = segment->duration;
1581   } else {
1582     segment->stop = desired_offset;
1583   }
1584
1585   if (qtdemux->fragmented)
1586     qtdemux->fragmented_seek_pending = TRUE;
1587
1588   return TRUE;
1589 }
1590
1591 /* do a seek in pull based mode */
1592 static gboolean
1593 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1594 {
1595   gdouble rate;
1596   GstFormat format;
1597   GstSeekFlags flags;
1598   GstSeekType cur_type, stop_type;
1599   gint64 cur, stop;
1600   gboolean flush;
1601   gboolean update;
1602   GstSegment seeksegment;
1603   guint32 seqnum = 0;
1604   GstEvent *flush_event;
1605
1606   if (event) {
1607     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1608
1609     gst_event_parse_seek (event, &rate, &format, &flags,
1610         &cur_type, &cur, &stop_type, &stop);
1611     seqnum = gst_event_get_seqnum (event);
1612
1613     /* we have to have a format as the segment format. Try to convert
1614      * if not. */
1615     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1616             stop_type, &stop))
1617       goto no_format;
1618
1619     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1620   } else {
1621     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1622     flags = 0;
1623   }
1624
1625   flush = flags & GST_SEEK_FLAG_FLUSH;
1626
1627   /* stop streaming, either by flushing or by pausing the task */
1628   if (flush) {
1629     flush_event = gst_event_new_flush_start ();
1630     if (seqnum)
1631       gst_event_set_seqnum (flush_event, seqnum);
1632     /* unlock upstream pull_range */
1633     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1634     /* make sure out loop function exits */
1635     gst_qtdemux_push_event (qtdemux, flush_event);
1636   } else {
1637     /* non flushing seek, pause the task */
1638     gst_pad_pause_task (qtdemux->sinkpad);
1639   }
1640
1641   /* wait for streaming to finish */
1642   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1643
1644   /* copy segment, we need this because we still need the old
1645    * segment when we close the current segment. */
1646   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1647
1648   if (event) {
1649     /* configure the segment with the seek variables */
1650     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1651     gst_segment_do_seek (&seeksegment, rate, format, flags,
1652         cur_type, cur, stop_type, stop, &update);
1653   }
1654
1655   /* now do the seek, this actually never returns FALSE */
1656   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1657
1658   /* prepare for streaming again */
1659   if (flush) {
1660     flush_event = gst_event_new_flush_stop (TRUE);
1661     if (seqnum)
1662       gst_event_set_seqnum (flush_event, seqnum);
1663
1664     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1665     gst_qtdemux_push_event (qtdemux, flush_event);
1666   }
1667
1668   /* commit the new segment */
1669   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1670
1671   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1672     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1673         qtdemux->segment.format, qtdemux->segment.position);
1674     if (seqnum)
1675       gst_message_set_seqnum (msg, seqnum);
1676     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1677   }
1678
1679   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1680   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1681       qtdemux->sinkpad, NULL);
1682
1683   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1684
1685   return TRUE;
1686
1687   /* ERRORS */
1688 no_format:
1689   {
1690     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1691     return FALSE;
1692   }
1693 }
1694
1695 static gboolean
1696 qtdemux_ensure_index (GstQTDemux * qtdemux)
1697 {
1698   guint i;
1699
1700   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1701
1702   /* Build complete index */
1703   for (i = 0; i < qtdemux->n_streams; i++) {
1704     QtDemuxStream *stream = qtdemux->streams[i];
1705
1706     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1707       goto parse_error;
1708   }
1709   return TRUE;
1710
1711   /* ERRORS */
1712 parse_error:
1713   {
1714     GST_LOG_OBJECT (qtdemux,
1715         "Building complete index of stream %u for seeking failed!", i);
1716     return FALSE;
1717   }
1718 }
1719
1720 static gboolean
1721 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1722     GstEvent * event)
1723 {
1724   gboolean res = TRUE;
1725   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1726
1727   switch (GST_EVENT_TYPE (event)) {
1728     case GST_EVENT_SEEK:
1729     {
1730 #ifndef GST_DISABLE_GST_DEBUG
1731       GstClockTime ts = gst_util_get_timestamp ();
1732 #endif
1733
1734       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1735         /* seek should be handled by upstream, we might need to re-download fragments */
1736         GST_DEBUG_OBJECT (qtdemux,
1737             "let upstream handle seek for fragmented playback");
1738         goto upstream;
1739       }
1740
1741       /* Build complete index for seeking;
1742        * if not a fragmented file at least */
1743       if (!qtdemux->fragmented)
1744         if (!qtdemux_ensure_index (qtdemux))
1745           goto index_failed;
1746 #ifndef GST_DISABLE_GST_DEBUG
1747       ts = gst_util_get_timestamp () - ts;
1748       GST_INFO_OBJECT (qtdemux,
1749           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1750 #endif
1751     }
1752       if (qtdemux->pullbased) {
1753         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1754       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1755         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1756         res = TRUE;
1757       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1758           && !qtdemux->fragmented) {
1759         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1760       } else {
1761         GST_DEBUG_OBJECT (qtdemux,
1762             "ignoring seek in push mode in current state");
1763         res = FALSE;
1764       }
1765       gst_event_unref (event);
1766       break;
1767     default:
1768     upstream:
1769       res = gst_pad_event_default (pad, parent, event);
1770       break;
1771   }
1772
1773 done:
1774   return res;
1775
1776   /* ERRORS */
1777 index_failed:
1778   {
1779     GST_ERROR_OBJECT (qtdemux, "Index failed");
1780     gst_event_unref (event);
1781     res = FALSE;
1782     goto done;
1783   }
1784 }
1785
1786 /* stream/index return sample that is min/max w.r.t. byte position,
1787  * time is min/max w.r.t. time of samples,
1788  * the latter need not be time of the former sample */
1789 static void
1790 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1791     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1792 {
1793   gint i, n, index;
1794   gint64 time, min_time;
1795   QtDemuxStream *stream;
1796
1797   min_time = -1;
1798   stream = NULL;
1799   index = -1;
1800
1801   for (n = 0; n < qtdemux->n_streams; ++n) {
1802     QtDemuxStream *str;
1803     gint inc;
1804     gboolean set_sample;
1805
1806     str = qtdemux->streams[n];
1807     set_sample = !set;
1808
1809     if (fw) {
1810       i = 0;
1811       inc = 1;
1812     } else {
1813       i = str->n_samples - 1;
1814       inc = -1;
1815     }
1816
1817     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1818       if (str->samples[i].size == 0)
1819         continue;
1820
1821       if (fw && (str->samples[i].offset < byte_pos))
1822         continue;
1823
1824       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1825         continue;
1826
1827       /* move stream to first available sample */
1828       if (set) {
1829         gst_qtdemux_move_stream (qtdemux, str, i);
1830         set_sample = TRUE;
1831       }
1832
1833       /* avoid index from sparse streams since they might be far away */
1834       if (!str->sparse) {
1835         /* determine min/max time */
1836         time = QTSAMPLE_PTS (str, &str->samples[i]);
1837         if (min_time == -1 || (!fw && time > min_time) ||
1838             (fw && time < min_time)) {
1839           min_time = time;
1840         }
1841
1842         /* determine stream with leading sample, to get its position */
1843         if (!stream ||
1844             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1845             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1846           stream = str;
1847           index = i;
1848         }
1849       }
1850       break;
1851     }
1852
1853     /* no sample for this stream, mark eos */
1854     if (!set_sample)
1855       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1856   }
1857
1858   if (_time)
1859     *_time = min_time;
1860   if (_stream)
1861     *_stream = stream;
1862   if (_index)
1863     *_index = index;
1864 }
1865
1866 static QtDemuxStream *
1867 _create_stream (void)
1868 {
1869   QtDemuxStream *stream;
1870
1871   stream = g_new0 (QtDemuxStream, 1);
1872   /* new streams always need a discont */
1873   stream->discont = TRUE;
1874   /* we enable clipping for raw audio/video streams */
1875   stream->need_clip = FALSE;
1876   stream->need_process = FALSE;
1877   stream->segment_index = -1;
1878   stream->time_position = 0;
1879   stream->sample_index = -1;
1880   stream->offset_in_sample = 0;
1881   stream->new_stream = TRUE;
1882   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1883   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1884   stream->protected = FALSE;
1885   stream->protection_scheme_type = 0;
1886   stream->protection_scheme_version = 0;
1887   stream->protection_scheme_info = NULL;
1888   stream->n_samples_moof = 0;
1889   stream->duration_moof = 0;
1890   stream->duration_last_moof = 0;
1891   stream->alignment = 1;
1892   g_queue_init (&stream->protection_scheme_event_queue);
1893   return stream;
1894 }
1895
1896 static gboolean
1897 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1898 {
1899   GstStructure *structure;
1900   const gchar *variant;
1901   const GstCaps *mediacaps = NULL;
1902
1903   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1904
1905   structure = gst_caps_get_structure (caps, 0);
1906   variant = gst_structure_get_string (structure, "variant");
1907
1908   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1909     QtDemuxStream *stream;
1910     const GValue *value;
1911
1912     demux->fragmented = TRUE;
1913     demux->mss_mode = TRUE;
1914
1915     if (demux->n_streams > 1) {
1916       /* can't do this, we can only renegotiate for another mss format */
1917       return FALSE;
1918     }
1919
1920     value = gst_structure_get_value (structure, "media-caps");
1921     /* create stream */
1922     if (value) {
1923       const GValue *timescale_v;
1924
1925       /* TODO update when stream changes during playback */
1926
1927       if (demux->n_streams == 0) {
1928         stream = _create_stream ();
1929         demux->streams[demux->n_streams] = stream;
1930         demux->n_streams = 1;
1931       } else {
1932         stream = demux->streams[0];
1933       }
1934
1935       timescale_v = gst_structure_get_value (structure, "timescale");
1936       if (timescale_v) {
1937         stream->timescale = g_value_get_uint64 (timescale_v);
1938       } else {
1939         /* default mss timescale */
1940         stream->timescale = 10000000;
1941       }
1942       demux->timescale = stream->timescale;
1943
1944       mediacaps = gst_value_get_caps (value);
1945       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1946         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1947             mediacaps);
1948         stream->new_caps = TRUE;
1949       }
1950       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1951       structure = gst_caps_get_structure (mediacaps, 0);
1952       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1953         stream->subtype = FOURCC_vide;
1954
1955         gst_structure_get_int (structure, "width", &stream->width);
1956         gst_structure_get_int (structure, "height", &stream->height);
1957         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1958             &stream->fps_d);
1959       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1960         gint rate = 0;
1961         stream->subtype = FOURCC_soun;
1962         gst_structure_get_int (structure, "channels", &stream->n_channels);
1963         gst_structure_get_int (structure, "rate", &rate);
1964         stream->rate = rate;
1965       }
1966     }
1967     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1968   } else {
1969     demux->mss_mode = FALSE;
1970   }
1971
1972   return TRUE;
1973 }
1974
1975 static void
1976 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1977 {
1978   gint n;
1979
1980   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1981   gst_pad_stop_task (qtdemux->sinkpad);
1982
1983   if (hard || qtdemux->upstream_format_is_time) {
1984     qtdemux->state = QTDEMUX_STATE_INITIAL;
1985     qtdemux->neededbytes = 16;
1986     qtdemux->todrop = 0;
1987     qtdemux->pullbased = FALSE;
1988     qtdemux->posted_redirect = FALSE;
1989     qtdemux->first_mdat = -1;
1990     qtdemux->header_size = 0;
1991     qtdemux->mdatoffset = -1;
1992     qtdemux->restoredata_offset = -1;
1993     if (qtdemux->mdatbuffer)
1994       gst_buffer_unref (qtdemux->mdatbuffer);
1995     if (qtdemux->restoredata_buffer)
1996       gst_buffer_unref (qtdemux->restoredata_buffer);
1997     qtdemux->mdatbuffer = NULL;
1998     qtdemux->restoredata_buffer = NULL;
1999     qtdemux->mdatleft = 0;
2000     if (qtdemux->comp_brands)
2001       gst_buffer_unref (qtdemux->comp_brands);
2002     qtdemux->comp_brands = NULL;
2003     qtdemux->last_moov_offset = -1;
2004     if (qtdemux->moov_node_compressed) {
2005       g_node_destroy (qtdemux->moov_node_compressed);
2006       if (qtdemux->moov_node)
2007         g_free (qtdemux->moov_node->data);
2008     }
2009     qtdemux->moov_node_compressed = NULL;
2010     if (qtdemux->moov_node)
2011       g_node_destroy (qtdemux->moov_node);
2012     qtdemux->moov_node = NULL;
2013     if (qtdemux->tag_list)
2014       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2015     qtdemux->tag_list = NULL;
2016 #if 0
2017     if (qtdemux->element_index)
2018       gst_object_unref (qtdemux->element_index);
2019     qtdemux->element_index = NULL;
2020 #endif
2021     qtdemux->major_brand = 0;
2022     if (qtdemux->pending_newsegment)
2023       gst_event_unref (qtdemux->pending_newsegment);
2024     qtdemux->pending_newsegment = NULL;
2025     qtdemux->upstream_format_is_time = FALSE;
2026     qtdemux->upstream_seekable = FALSE;
2027     qtdemux->upstream_size = 0;
2028
2029     qtdemux->fragment_start = -1;
2030     qtdemux->fragment_start_offset = -1;
2031     qtdemux->duration = 0;
2032     qtdemux->moof_offset = 0;
2033     qtdemux->chapters_track_id = 0;
2034     qtdemux->have_group_id = FALSE;
2035     qtdemux->group_id = G_MAXUINT;
2036
2037     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2038         NULL);
2039     g_queue_clear (&qtdemux->protection_event_queue);
2040   }
2041   qtdemux->offset = 0;
2042   gst_adapter_clear (qtdemux->adapter);
2043   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2044   qtdemux->segment_seqnum = 0;
2045
2046   if (hard) {
2047     for (n = 0; n < qtdemux->n_streams; n++) {
2048       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2049       qtdemux->streams[n] = NULL;
2050     }
2051     qtdemux->n_streams = 0;
2052     qtdemux->n_video_streams = 0;
2053     qtdemux->n_audio_streams = 0;
2054     qtdemux->n_sub_streams = 0;
2055     qtdemux->exposed = FALSE;
2056     qtdemux->fragmented = FALSE;
2057     qtdemux->mss_mode = FALSE;
2058     gst_caps_replace (&qtdemux->media_caps, NULL);
2059     qtdemux->timescale = 0;
2060     qtdemux->got_moov = FALSE;
2061     if (qtdemux->protection_system_ids) {
2062       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2063       qtdemux->protection_system_ids = NULL;
2064     }
2065   } else if (qtdemux->mss_mode) {
2066     gst_flow_combiner_reset (qtdemux->flowcombiner);
2067     for (n = 0; n < qtdemux->n_streams; n++)
2068       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2069   } else {
2070     gst_flow_combiner_reset (qtdemux->flowcombiner);
2071     for (n = 0; n < qtdemux->n_streams; n++) {
2072       qtdemux->streams[n]->sent_eos = FALSE;
2073       qtdemux->streams[n]->time_position = 0;
2074       qtdemux->streams[n]->accumulated_base = 0;
2075     }
2076     if (!qtdemux->pending_newsegment) {
2077       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2078       if (qtdemux->segment_seqnum)
2079         gst_event_set_seqnum (qtdemux->pending_newsegment,
2080             qtdemux->segment_seqnum);
2081     }
2082   }
2083 }
2084
2085
2086 /* Maps the @segment to the qt edts internal segments and pushes
2087  * the correspnding segment event.
2088  *
2089  * If it ends up being at a empty segment, a gap will be pushed and the next
2090  * edts segment will be activated in sequence.
2091  *
2092  * To be used in push-mode only */
2093 static void
2094 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2095 {
2096   gint n, i;
2097
2098   for (n = 0; n < qtdemux->n_streams; n++) {
2099     QtDemuxStream *stream = qtdemux->streams[n];
2100
2101     stream->time_position = segment->start;
2102
2103     /* in push mode we should be guaranteed that we will have empty segments
2104      * at the beginning and then one segment after, other scenarios are not
2105      * supported and are discarded when parsing the edts */
2106     for (i = 0; i < stream->n_segments; i++) {
2107       if (stream->segments[i].stop_time > segment->start) {
2108         gst_qtdemux_activate_segment (qtdemux, stream, i,
2109             stream->time_position);
2110         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2111           /* push the empty segment and move to the next one */
2112           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2113               stream->time_position);
2114           continue;
2115         }
2116
2117         g_assert (i == stream->n_segments - 1);
2118       }
2119     }
2120   }
2121 }
2122
2123 static gboolean
2124 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2125     GstEvent * event)
2126 {
2127   GstQTDemux *demux = GST_QTDEMUX (parent);
2128   gboolean res = TRUE;
2129
2130   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2131
2132   switch (GST_EVENT_TYPE (event)) {
2133     case GST_EVENT_SEGMENT:
2134     {
2135       gint64 offset = 0;
2136       QtDemuxStream *stream;
2137       gint idx;
2138       GstSegment segment;
2139
2140       /* some debug output */
2141       gst_event_copy_segment (event, &segment);
2142       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2143           &segment);
2144
2145       /* erase any previously set segment */
2146       gst_event_replace (&demux->pending_newsegment, NULL);
2147
2148       if (segment.format == GST_FORMAT_TIME) {
2149         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2150         gst_event_replace (&demux->pending_newsegment, event);
2151         demux->upstream_format_is_time = TRUE;
2152       } else {
2153         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2154             "not in time format");
2155
2156         /* chain will send initial newsegment after pads have been added */
2157         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2158           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2159           goto exit;
2160         }
2161       }
2162
2163       /* check if this matches a time seek we received previously
2164        * FIXME for backwards compatibility reasons we use the
2165        * seek_offset here to compare. In the future we might want to
2166        * change this to use the seqnum as it uniquely should identify
2167        * the segment that corresponds to the seek. */
2168       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2169           ", received segment offset %" G_GINT64_FORMAT,
2170           demux->seek_offset, segment.start);
2171       if (segment.format == GST_FORMAT_BYTES
2172           && demux->seek_offset == segment.start) {
2173         GST_OBJECT_LOCK (demux);
2174         offset = segment.start;
2175
2176         segment.format = GST_FORMAT_TIME;
2177         segment.start = demux->push_seek_start;
2178         segment.stop = demux->push_seek_stop;
2179         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2180             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2181             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2182         GST_OBJECT_UNLOCK (demux);
2183       }
2184
2185       /* we only expect a BYTE segment, e.g. following a seek */
2186       if (segment.format == GST_FORMAT_BYTES) {
2187         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2188           offset = segment.start;
2189
2190           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2191               NULL, (gint64 *) & segment.start);
2192           if ((gint64) segment.start < 0)
2193             segment.start = 0;
2194         }
2195         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2196           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2197               NULL, (gint64 *) & segment.stop);
2198           /* keyframe seeking should already arrange for start >= stop,
2199            * but make sure in other rare cases */
2200           segment.stop = MAX (segment.stop, segment.start);
2201         }
2202       } else if (segment.format == GST_FORMAT_TIME) {
2203         /* push all data on the adapter before starting this
2204          * new segment */
2205         gst_qtdemux_process_adapter (demux, TRUE);
2206       } else {
2207         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2208         goto exit;
2209       }
2210
2211       /* We shouldn't modify upstream driven TIME FORMAT segment */
2212       if (!demux->upstream_format_is_time) {
2213         /* accept upstream's notion of segment and distribute along */
2214         segment.format = GST_FORMAT_TIME;
2215         segment.position = segment.time = segment.start;
2216         segment.duration = demux->segment.duration;
2217         segment.base = gst_segment_to_running_time (&demux->segment,
2218             GST_FORMAT_TIME, demux->segment.position);
2219       }
2220
2221       gst_segment_copy_into (&segment, &demux->segment);
2222       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2223
2224       /* map segment to internal qt segments and push on each stream */
2225       if (demux->n_streams) {
2226         if (demux->fragmented) {
2227           GstEvent *segment_event = gst_event_new_segment (&segment);
2228
2229           gst_event_replace (&demux->pending_newsegment, NULL);
2230           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2231           gst_qtdemux_push_event (demux, segment_event);
2232         } else {
2233           gst_event_replace (&demux->pending_newsegment, NULL);
2234           gst_qtdemux_map_and_push_segments (demux, &segment);
2235         }
2236       }
2237
2238       /* clear leftover in current segment, if any */
2239       gst_adapter_clear (demux->adapter);
2240
2241       /* set up streaming thread */
2242       demux->offset = offset;
2243       if (demux->upstream_format_is_time) {
2244         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2245             "set values to restart reading from a new atom");
2246         demux->neededbytes = 16;
2247         demux->todrop = 0;
2248       } else {
2249         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2250             NULL);
2251         if (stream) {
2252           demux->todrop = stream->samples[idx].offset - offset;
2253           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2254         } else {
2255           /* set up for EOS */
2256           demux->neededbytes = -1;
2257           demux->todrop = 0;
2258         }
2259       }
2260     exit:
2261       gst_event_unref (event);
2262       res = TRUE;
2263       goto drop;
2264     }
2265     case GST_EVENT_FLUSH_START:
2266     {
2267       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2268         gst_event_unref (event);
2269         goto drop;
2270       }
2271       break;
2272     }
2273     case GST_EVENT_FLUSH_STOP:
2274     {
2275       guint64 dur;
2276
2277       dur = demux->segment.duration;
2278       gst_qtdemux_reset (demux, FALSE);
2279       demux->segment.duration = dur;
2280
2281       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2282         gst_event_unref (event);
2283         goto drop;
2284       }
2285       break;
2286     }
2287     case GST_EVENT_EOS:
2288       /* If we are in push mode, and get an EOS before we've seen any streams,
2289        * then error out - we have nowhere to send the EOS */
2290       if (!demux->pullbased) {
2291         gint i;
2292         gboolean has_valid_stream = FALSE;
2293         for (i = 0; i < demux->n_streams; i++) {
2294           if (demux->streams[i]->pad != NULL) {
2295             has_valid_stream = TRUE;
2296             break;
2297           }
2298         }
2299         if (!has_valid_stream)
2300           gst_qtdemux_post_no_playable_stream_error (demux);
2301         else {
2302           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2303               (guint) gst_adapter_available (demux->adapter));
2304           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2305             res = FALSE;
2306           }
2307         }
2308       }
2309       break;
2310     case GST_EVENT_CAPS:{
2311       GstCaps *caps = NULL;
2312
2313       gst_event_parse_caps (event, &caps);
2314       gst_qtdemux_setcaps (demux, caps);
2315       res = TRUE;
2316       gst_event_unref (event);
2317       goto drop;
2318     }
2319     case GST_EVENT_PROTECTION:
2320     {
2321       const gchar *system_id = NULL;
2322
2323       gst_event_parse_protection (event, &system_id, NULL, NULL);
2324       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2325           system_id);
2326       gst_qtdemux_append_protection_system_id (demux, system_id);
2327       /* save the event for later, for source pads that have not been created */
2328       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2329       /* send it to all pads that already exist */
2330       gst_qtdemux_push_event (demux, event);
2331       res = TRUE;
2332       goto drop;
2333     }
2334     default:
2335       break;
2336   }
2337
2338   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2339
2340 drop:
2341   return res;
2342 }
2343
2344 #if 0
2345 static void
2346 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2347 {
2348   GstQTDemux *demux = GST_QTDEMUX (element);
2349
2350   GST_OBJECT_LOCK (demux);
2351   if (demux->element_index)
2352     gst_object_unref (demux->element_index);
2353   if (index) {
2354     demux->element_index = gst_object_ref (index);
2355   } else {
2356     demux->element_index = NULL;
2357   }
2358   GST_OBJECT_UNLOCK (demux);
2359   /* object lock might be taken again */
2360   if (index)
2361     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2362   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2363       demux->element_index, demux->index_id);
2364 }
2365
2366 static GstIndex *
2367 gst_qtdemux_get_index (GstElement * element)
2368 {
2369   GstIndex *result = NULL;
2370   GstQTDemux *demux = GST_QTDEMUX (element);
2371
2372   GST_OBJECT_LOCK (demux);
2373   if (demux->element_index)
2374     result = gst_object_ref (demux->element_index);
2375   GST_OBJECT_UNLOCK (demux);
2376
2377   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2378
2379   return result;
2380 }
2381 #endif
2382
2383 static void
2384 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2385 {
2386   g_free ((gpointer) stream->stco.data);
2387   stream->stco.data = NULL;
2388   g_free ((gpointer) stream->stsz.data);
2389   stream->stsz.data = NULL;
2390   g_free ((gpointer) stream->stsc.data);
2391   stream->stsc.data = NULL;
2392   g_free ((gpointer) stream->stts.data);
2393   stream->stts.data = NULL;
2394   g_free ((gpointer) stream->stss.data);
2395   stream->stss.data = NULL;
2396   g_free ((gpointer) stream->stps.data);
2397   stream->stps.data = NULL;
2398   g_free ((gpointer) stream->ctts.data);
2399   stream->ctts.data = NULL;
2400 }
2401
2402 static void
2403 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2404     QtDemuxStream * stream)
2405 {
2406   g_free (stream->segments);
2407   stream->segments = NULL;
2408   stream->segment_index = -1;
2409   stream->accumulated_base = 0;
2410 }
2411
2412 static void
2413 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2414     QtDemuxStream * stream)
2415 {
2416   g_free (stream->samples);
2417   stream->samples = NULL;
2418   gst_qtdemux_stbl_free (stream);
2419
2420   /* fragments */
2421   g_free (stream->ra_entries);
2422   stream->ra_entries = NULL;
2423   stream->n_ra_entries = 0;
2424
2425   stream->sample_index = -1;
2426   stream->stbl_index = -1;
2427   stream->n_samples = 0;
2428   stream->time_position = 0;
2429
2430   stream->n_samples_moof = 0;
2431   stream->duration_moof = 0;
2432   stream->duration_last_moof = 0;
2433 }
2434
2435 static void
2436 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2437 {
2438   if (stream->allocator)
2439     gst_object_unref (stream->allocator);
2440   while (stream->buffers) {
2441     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2442     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2443   }
2444   if (stream->rgb8_palette) {
2445     gst_memory_unref (stream->rgb8_palette);
2446     stream->rgb8_palette = NULL;
2447   }
2448
2449   if (stream->pending_tags)
2450     gst_tag_list_unref (stream->pending_tags);
2451   stream->pending_tags = NULL;
2452   g_free (stream->redirect_uri);
2453   stream->redirect_uri = NULL;
2454   stream->sent_eos = FALSE;
2455   stream->sparse = FALSE;
2456   stream->protected = FALSE;
2457   if (stream->protection_scheme_info) {
2458     if (stream->protection_scheme_type == FOURCC_cenc) {
2459       QtDemuxCencSampleSetInfo *info =
2460           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2461       if (info->default_properties)
2462         gst_structure_free (info->default_properties);
2463       if (info->crypto_info)
2464         g_ptr_array_free (info->crypto_info, TRUE);
2465     }
2466     g_free (stream->protection_scheme_info);
2467     stream->protection_scheme_info = NULL;
2468   }
2469   stream->protection_scheme_type = 0;
2470   stream->protection_scheme_version = 0;
2471   g_queue_foreach (&stream->protection_scheme_event_queue,
2472       (GFunc) gst_event_unref, NULL);
2473   g_queue_clear (&stream->protection_scheme_event_queue);
2474   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2475   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2476 }
2477
2478 static void
2479 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2480 {
2481   gst_qtdemux_stream_clear (qtdemux, stream);
2482   if (stream->caps)
2483     gst_caps_unref (stream->caps);
2484   stream->caps = NULL;
2485   if (stream->pad) {
2486     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2487     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2488   }
2489   g_free (stream);
2490 }
2491
2492 static void
2493 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2494 {
2495   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2496
2497   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2498   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2499   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2500   qtdemux->n_streams--;
2501 }
2502
2503 static GstStateChangeReturn
2504 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2505 {
2506   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2507   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2508
2509   switch (transition) {
2510     case GST_STATE_CHANGE_PAUSED_TO_READY:
2511       break;
2512     default:
2513       break;
2514   }
2515
2516   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2517
2518   switch (transition) {
2519     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2520       gst_qtdemux_reset (qtdemux, TRUE);
2521       break;
2522     }
2523     default:
2524       break;
2525   }
2526
2527   return result;
2528 }
2529
2530 static void
2531 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2532 {
2533   /* counts as header data */
2534   qtdemux->header_size += length;
2535
2536   /* only consider at least a sufficiently complete ftyp atom */
2537   if (length >= 20) {
2538     GstBuffer *buf;
2539
2540     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2541     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2542         GST_FOURCC_ARGS (qtdemux->major_brand));
2543     if (qtdemux->comp_brands)
2544       gst_buffer_unref (qtdemux->comp_brands);
2545     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2546     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2547   }
2548 }
2549
2550 static void
2551 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2552     GstTagList * xmptaglist)
2553 {
2554   /* Strip out bogus fields */
2555   if (xmptaglist) {
2556     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2557       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2558       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2559     } else {
2560       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2561     }
2562
2563     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2564
2565     /* prioritize native tags using _KEEP mode */
2566     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2567     gst_tag_list_unref (xmptaglist);
2568   }
2569 }
2570
2571 static void
2572 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2573     guint offset)
2574 {
2575   GstByteReader br;
2576   guint8 version;
2577   guint32 flags = 0;
2578   guint i;
2579   guint8 iv_size = 8;
2580   QtDemuxStream *stream;
2581   GstStructure *structure;
2582   QtDemuxCencSampleSetInfo *ss_info = NULL;
2583   const gchar *system_id;
2584   gboolean uses_sub_sample_encryption = FALSE;
2585
2586   if (qtdemux->n_streams == 0)
2587     return;
2588
2589   stream = qtdemux->streams[0];
2590
2591   structure = gst_caps_get_structure (stream->caps, 0);
2592   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2593     GST_WARNING_OBJECT (qtdemux,
2594         "Attempting PIFF box parsing on an unencrypted stream.");
2595     return;
2596   }
2597
2598   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2599       G_TYPE_STRING, &system_id, NULL);
2600   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2601
2602   stream->protected = TRUE;
2603   stream->protection_scheme_type = FOURCC_cenc;
2604
2605   if (!stream->protection_scheme_info)
2606     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2607
2608   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2609
2610   if (ss_info->default_properties)
2611     gst_structure_free (ss_info->default_properties);
2612
2613   ss_info->default_properties =
2614       gst_structure_new ("application/x-cenc",
2615       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2616
2617   if (ss_info->crypto_info) {
2618     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2619     g_ptr_array_free (ss_info->crypto_info, TRUE);
2620     ss_info->crypto_info = NULL;
2621   }
2622
2623   /* skip UUID */
2624   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2625
2626   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2627     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2628     return;
2629   }
2630
2631   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2632     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2633     return;
2634   }
2635
2636   if ((flags & 0x000001)) {
2637     guint32 algorithm_id = 0;
2638     const guint8 *kid;
2639     GstBuffer *kid_buf;
2640     gboolean is_encrypted = TRUE;
2641
2642     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2643       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2644       return;
2645     }
2646
2647     algorithm_id >>= 8;
2648     if (algorithm_id == 0) {
2649       is_encrypted = FALSE;
2650     } else if (algorithm_id == 1) {
2651       /* FIXME: maybe store this in properties? */
2652       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2653     } else if (algorithm_id == 2) {
2654       /* FIXME: maybe store this in properties? */
2655       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2656     }
2657
2658     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2659       return;
2660
2661     if (!gst_byte_reader_get_data (&br, 16, &kid))
2662       return;
2663
2664     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2665     gst_buffer_fill (kid_buf, 0, kid, 16);
2666     if (ss_info->default_properties)
2667       gst_structure_free (ss_info->default_properties);
2668     ss_info->default_properties =
2669         gst_structure_new ("application/x-cenc",
2670         "iv_size", G_TYPE_UINT, iv_size,
2671         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2672         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2673     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2674         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2675     gst_buffer_unref (kid_buf);
2676   } else if ((flags & 0x000002)) {
2677     uses_sub_sample_encryption = TRUE;
2678   }
2679
2680   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2681     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2682     return;
2683   }
2684
2685   ss_info->crypto_info =
2686       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2687       (GDestroyNotify) qtdemux_gst_structure_free);
2688
2689   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2690     GstStructure *properties;
2691     guint8 *data;
2692     GstBuffer *buf;
2693
2694     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2695     if (properties == NULL) {
2696       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2697       return;
2698     }
2699
2700     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2701       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2702       gst_structure_free (properties);
2703       return;
2704     }
2705     buf = gst_buffer_new_wrapped (data, iv_size);
2706     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2707     gst_buffer_unref (buf);
2708
2709     if (uses_sub_sample_encryption) {
2710       guint16 n_subsamples;
2711
2712       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2713           || n_subsamples == 0) {
2714         GST_ERROR_OBJECT (qtdemux,
2715             "failed to get subsample count for sample %u", i);
2716         gst_structure_free (properties);
2717         return;
2718       }
2719       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2720       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2721         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2722             i);
2723         gst_structure_free (properties);
2724         return;
2725       }
2726       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2727       gst_structure_set (properties,
2728           "subsample_count", G_TYPE_UINT, n_subsamples,
2729           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2730       gst_buffer_unref (buf);
2731     } else {
2732       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2733     }
2734
2735     g_ptr_array_add (ss_info->crypto_info, properties);
2736   }
2737 }
2738
2739 static void
2740 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2741 {
2742   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2743     0x97, 0xA9, 0x42, 0xE8,
2744     0x9C, 0x71, 0x99, 0x94,
2745     0x91, 0xE3, 0xAF, 0xAC
2746   };
2747   static const guint8 playready_uuid[] = {
2748     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2749     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2750   };
2751
2752   static const guint8 piff_sample_encryption_uuid[] = {
2753     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2754     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2755   };
2756
2757   guint offset;
2758
2759   /* counts as header data */
2760   qtdemux->header_size += length;
2761
2762   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2763
2764   if (length <= offset + 16) {
2765     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2766     return;
2767   }
2768
2769   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2770     GstBuffer *buf;
2771     GstTagList *taglist;
2772
2773     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2774         length - offset - 16, NULL);
2775     taglist = gst_tag_list_from_xmp_buffer (buf);
2776     gst_buffer_unref (buf);
2777
2778     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2779
2780   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2781     int len;
2782     const gunichar2 *s_utf16;
2783     char *contents;
2784
2785     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2786     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2787     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2788     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2789
2790     g_free (contents);
2791
2792     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2793         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2794         (NULL));
2795   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2796     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2797   } else {
2798     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2799         GST_READ_UINT32_LE (buffer + offset),
2800         GST_READ_UINT32_LE (buffer + offset + 4),
2801         GST_READ_UINT32_LE (buffer + offset + 8),
2802         GST_READ_UINT32_LE (buffer + offset + 12));
2803   }
2804 }
2805
2806 static void
2807 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2808 {
2809   GstSidxParser sidx_parser;
2810   GstIsoffParserResult res;
2811   guint consumed;
2812
2813   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2814
2815   res =
2816       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2817       &consumed);
2818   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2819   if (res == GST_ISOFF_QT_PARSER_DONE) {
2820     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2821   }
2822   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2823 }
2824
2825 /* caller verifies at least 8 bytes in buf */
2826 static void
2827 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2828     guint64 * plength, guint32 * pfourcc)
2829 {
2830   guint64 length;
2831   guint32 fourcc;
2832
2833   length = QT_UINT32 (data);
2834   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2835   fourcc = QT_FOURCC (data + 4);
2836   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2837
2838   if (length == 0) {
2839     length = G_MAXUINT64;
2840   } else if (length == 1 && size >= 16) {
2841     /* this means we have an extended size, which is the 64 bit value of
2842      * the next 8 bytes */
2843     length = QT_UINT64 (data + 8);
2844     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2845   }
2846
2847   if (plength)
2848     *plength = length;
2849   if (pfourcc)
2850     *pfourcc = fourcc;
2851 }
2852
2853 static gboolean
2854 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2855 {
2856   guint32 version = 0;
2857   GstClockTime duration = 0;
2858
2859   if (!gst_byte_reader_get_uint32_be (br, &version))
2860     goto failed;
2861
2862   version >>= 24;
2863   if (version == 1) {
2864     if (!gst_byte_reader_get_uint64_be (br, &duration))
2865       goto failed;
2866   } else {
2867     guint32 dur = 0;
2868
2869     if (!gst_byte_reader_get_uint32_be (br, &dur))
2870       goto failed;
2871     duration = dur;
2872   }
2873
2874   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2875   qtdemux->duration = duration;
2876
2877   return TRUE;
2878
2879 failed:
2880   {
2881     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2882     return FALSE;
2883   }
2884 }
2885
2886 static gboolean
2887 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2888     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2889 {
2890   if (!stream->parsed_trex && qtdemux->moov_node) {
2891     GNode *mvex, *trex;
2892     GstByteReader trex_data;
2893
2894     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2895     if (mvex) {
2896       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2897           &trex_data);
2898       while (trex) {
2899         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2900
2901         /* skip version/flags */
2902         if (!gst_byte_reader_skip (&trex_data, 4))
2903           goto next;
2904         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2905           goto next;
2906         if (id != stream->track_id)
2907           goto next;
2908         /* sample description index; ignore */
2909         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2910           goto next;
2911         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2912           goto next;
2913         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2914           goto next;
2915         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2916           goto next;
2917
2918         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2919             "duration %d,  size %d, flags 0x%x", stream->track_id,
2920             dur, size, flags);
2921
2922         stream->parsed_trex = TRUE;
2923         stream->def_sample_duration = dur;
2924         stream->def_sample_size = size;
2925         stream->def_sample_flags = flags;
2926
2927       next:
2928         /* iterate all siblings */
2929         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2930             &trex_data);
2931       }
2932     }
2933   }
2934
2935   *ds_duration = stream->def_sample_duration;
2936   *ds_size = stream->def_sample_size;
2937   *ds_flags = stream->def_sample_flags;
2938
2939   /* even then, above values are better than random ... */
2940   if (G_UNLIKELY (!stream->parsed_trex)) {
2941     GST_WARNING_OBJECT (qtdemux,
2942         "failed to find fragment defaults for stream %d", stream->track_id);
2943     return FALSE;
2944   }
2945
2946   return TRUE;
2947 }
2948
2949 /* This method should be called whenever a more accurate duration might
2950  * have been found. It will update all relevant variables if/where needed
2951  */
2952 static void
2953 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2954 {
2955   guint i;
2956   guint64 movdur;
2957   GstClockTime prevdur;
2958
2959   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2960
2961   if (movdur > qtdemux->duration) {
2962     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2963     GST_DEBUG_OBJECT (qtdemux,
2964         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2965         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2966     qtdemux->duration = movdur;
2967     GST_DEBUG_OBJECT (qtdemux,
2968         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2969         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2970         GST_TIME_ARGS (qtdemux->segment.stop));
2971     if (qtdemux->segment.duration == prevdur) {
2972       /* If the current segment has duration/stop identical to previous duration
2973        * update them also (because they were set at that point in time with
2974        * the wrong duration */
2975       /* We convert the value *from* the timescale version to avoid rounding errors */
2976       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2977       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2978       qtdemux->segment.duration = fixeddur;
2979       qtdemux->segment.stop = fixeddur;
2980     }
2981   }
2982   for (i = 0; i < qtdemux->n_streams; i++) {
2983     QtDemuxStream *stream = qtdemux->streams[i];
2984     if (stream) {
2985       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2986       if (movdur > stream->duration) {
2987         GST_DEBUG_OBJECT (qtdemux,
2988             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2989             GST_TIME_ARGS (duration));
2990         stream->duration = movdur;
2991         if (stream->dummy_segment) {
2992           /* Update all dummy values to new duration */
2993           stream->segments[0].stop_time = duration;
2994           stream->segments[0].duration = duration;
2995           stream->segments[0].media_stop = duration;
2996
2997           /* let downstream know we possibly have a new stop time */
2998           if (stream->segment_index != -1) {
2999             GstClockTime pos;
3000
3001             if (qtdemux->segment.rate >= 0) {
3002               pos = stream->segment.start;
3003             } else {
3004               pos = stream->segment.stop;
3005             }
3006
3007             gst_qtdemux_stream_update_segment (qtdemux, stream,
3008                 stream->segment_index, pos, NULL, NULL);
3009           }
3010         }
3011       }
3012     }
3013   }
3014 }
3015
3016 static gboolean
3017 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3018     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3019     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3020     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
3021 {
3022   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3023   guint64 timestamp;
3024   gint32 data_offset = 0;
3025   guint32 flags = 0, first_flags = 0, samples_count = 0;
3026   gint i;
3027   guint8 *data;
3028   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3029   QtDemuxSample *sample;
3030   gboolean ismv = FALSE;
3031   gint64 initial_offset;
3032
3033   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3034       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3035       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3036       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3037
3038   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3039     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3040     return TRUE;
3041   }
3042
3043   /* presence of stss or not can't really tell us much,
3044    * and flags and so on tend to be marginally reliable in these files */
3045   if (stream->subtype == FOURCC_soun) {
3046     GST_DEBUG_OBJECT (qtdemux,
3047         "sound track in fragmented file; marking all keyframes");
3048     stream->all_keyframe = TRUE;
3049   }
3050
3051   if (!gst_byte_reader_skip (trun, 1) ||
3052       !gst_byte_reader_get_uint24_be (trun, &flags))
3053     goto fail;
3054
3055   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3056     goto fail;
3057
3058   if (flags & TR_DATA_OFFSET) {
3059     /* note this is really signed */
3060     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3061       goto fail;
3062     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3063     /* default base offset = first byte of moof */
3064     if (*base_offset == -1) {
3065       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3066       *base_offset = moof_offset;
3067     }
3068     *running_offset = *base_offset + data_offset;
3069   } else {
3070     /* if no offset at all, that would mean data starts at moof start,
3071      * which is a bit wrong and is ismv crappy way, so compensate
3072      * assuming data is in mdat following moof */
3073     if (*base_offset == -1) {
3074       *base_offset = moof_offset + moof_length + 8;
3075       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3076       ismv = TRUE;
3077     }
3078     if (*running_offset == -1)
3079       *running_offset = *base_offset;
3080   }
3081
3082   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3083       *running_offset);
3084   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3085       data_offset, flags, samples_count);
3086
3087   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3088     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3089       GST_DEBUG_OBJECT (qtdemux,
3090           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3091       flags ^= TR_FIRST_SAMPLE_FLAGS;
3092     } else {
3093       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3094         goto fail;
3095       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3096     }
3097   }
3098
3099   /* FIXME ? spec says other bits should also be checked to determine
3100    * entry size (and prefix size for that matter) */
3101   entry_size = 0;
3102   dur_offset = size_offset = 0;
3103   if (flags & TR_SAMPLE_DURATION) {
3104     GST_LOG_OBJECT (qtdemux, "entry duration present");
3105     dur_offset = entry_size;
3106     entry_size += 4;
3107   }
3108   if (flags & TR_SAMPLE_SIZE) {
3109     GST_LOG_OBJECT (qtdemux, "entry size present");
3110     size_offset = entry_size;
3111     entry_size += 4;
3112   }
3113   if (flags & TR_SAMPLE_FLAGS) {
3114     GST_LOG_OBJECT (qtdemux, "entry flags present");
3115     flags_offset = entry_size;
3116     entry_size += 4;
3117   }
3118   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3119     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3120     ct_offset = entry_size;
3121     entry_size += 4;
3122   }
3123
3124   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3125     goto fail;
3126   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3127
3128   if (stream->n_samples + samples_count >=
3129       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3130     goto index_too_big;
3131
3132   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3133       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3134       (stream->n_samples + samples_count) *
3135       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3136
3137   /* create a new array of samples if it's the first sample parsed */
3138   if (stream->n_samples == 0) {
3139     g_assert (stream->samples == NULL);
3140     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3141     /* or try to reallocate it with space enough to insert the new samples */
3142   } else
3143     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3144         stream->n_samples + samples_count);
3145   if (stream->samples == NULL)
3146     goto out_of_memory;
3147
3148   if (qtdemux->fragment_start != -1) {
3149     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3150     qtdemux->fragment_start = -1;
3151   } else {
3152     if (stream->n_samples == 0) {
3153       if (decode_ts > 0) {
3154         timestamp = decode_ts;
3155       } else if (stream->pending_seek != NULL) {
3156         /* if we don't have a timestamp from a tfdt box, we'll use the one
3157          * from the mfra seek table */
3158         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3159             GST_TIME_ARGS (stream->pending_seek->ts));
3160
3161         /* FIXME: this is not fully correct, the timestamp refers to the random
3162          * access sample refered to in the tfra entry, which may not necessarily
3163          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3164         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3165       } else {
3166         timestamp = 0;
3167       }
3168
3169       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3170       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3171           GST_TIME_ARGS (gst_ts));
3172     } else {
3173       /* subsequent fragments extend stream */
3174       timestamp =
3175           stream->samples[stream->n_samples - 1].timestamp +
3176           stream->samples[stream->n_samples - 1].duration;
3177
3178       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3179        * difference (1 sec.) between decode_ts and timestamp, prefer the
3180        * former */
3181       if (decode_ts != 0 && !qtdemux->upstream_format_is_time
3182           && ABSDIFF (decode_ts, timestamp) >
3183           MAX (stream->duration_last_moof / 2,
3184               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3185         GST_INFO_OBJECT (qtdemux,
3186             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3187             ") are significantly different (more than %" GST_TIME_FORMAT
3188             "), using decode_ts",
3189             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3190             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3191             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3192                     MAX (stream->duration_last_moof / 2,
3193                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3194         timestamp = decode_ts;
3195       }
3196
3197       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3198       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3199           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3200     }
3201   }
3202
3203   initial_offset = *running_offset;
3204
3205   sample = stream->samples + stream->n_samples;
3206   for (i = 0; i < samples_count; i++) {
3207     guint32 dur, size, sflags, ct;
3208
3209     /* first read sample data */
3210     if (flags & TR_SAMPLE_DURATION) {
3211       dur = QT_UINT32 (data + dur_offset);
3212     } else {
3213       dur = d_sample_duration;
3214     }
3215     if (flags & TR_SAMPLE_SIZE) {
3216       size = QT_UINT32 (data + size_offset);
3217     } else {
3218       size = d_sample_size;
3219     }
3220     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3221       if (i == 0) {
3222         sflags = first_flags;
3223       } else {
3224         sflags = d_sample_flags;
3225       }
3226     } else if (flags & TR_SAMPLE_FLAGS) {
3227       sflags = QT_UINT32 (data + flags_offset);
3228     } else {
3229       sflags = d_sample_flags;
3230     }
3231     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3232       ct = QT_UINT32 (data + ct_offset);
3233     } else {
3234       ct = 0;
3235     }
3236     data += entry_size;
3237
3238     /* fill the sample information */
3239     sample->offset = *running_offset;
3240     sample->pts_offset = ct;
3241     sample->size = size;
3242     sample->timestamp = timestamp;
3243     sample->duration = dur;
3244     /* sample-is-difference-sample */
3245     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3246      * now idea how it relates to bitfield other than massive LE/BE confusion */
3247     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3248     *running_offset += size;
3249     timestamp += dur;
3250     stream->duration_moof += dur;
3251     sample++;
3252   }
3253
3254   /* Update total duration if needed */
3255   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3256
3257   /* Pre-emptively figure out size of mdat based on trun information.
3258    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3259    * size, else we will still be able to use this when dealing with gap'ed
3260    * input */
3261   qtdemux->mdatleft = *running_offset - initial_offset;
3262
3263   stream->n_samples += samples_count;
3264   stream->n_samples_moof += samples_count;
3265
3266   if (stream->pending_seek != NULL)
3267     stream->pending_seek = NULL;
3268
3269   return TRUE;
3270
3271 fail:
3272   {
3273     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3274     return FALSE;
3275   }
3276 out_of_memory:
3277   {
3278     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3279         stream->n_samples);
3280     return FALSE;
3281   }
3282 index_too_big:
3283   {
3284     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3285         "be larger than %uMB (broken file?)", stream->n_samples,
3286         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3287     return FALSE;
3288   }
3289 }
3290
3291 /* find stream with @id */
3292 static inline QtDemuxStream *
3293 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3294 {
3295   QtDemuxStream *stream;
3296   gint i;
3297
3298   /* check */
3299   if (G_UNLIKELY (!id)) {
3300     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3301     return NULL;
3302   }
3303
3304   /* try to get it fast and simple */
3305   if (G_LIKELY (id <= qtdemux->n_streams)) {
3306     stream = qtdemux->streams[id - 1];
3307     if (G_LIKELY (stream->track_id == id))
3308       return stream;
3309   }
3310
3311   /* linear search otherwise */
3312   for (i = 0; i < qtdemux->n_streams; i++) {
3313     stream = qtdemux->streams[i];
3314     if (stream->track_id == id)
3315       return stream;
3316   }
3317   if (qtdemux->mss_mode) {
3318     /* mss should have only 1 stream anyway */
3319     return qtdemux->streams[0];
3320   }
3321
3322   return NULL;
3323 }
3324
3325 static gboolean
3326 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3327     guint32 * fragment_number)
3328 {
3329   if (!gst_byte_reader_skip (mfhd, 4))
3330     goto fail;
3331   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3332     goto fail;
3333   return TRUE;
3334 fail:
3335   {
3336     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3337     return FALSE;
3338   }
3339 }
3340
3341 static gboolean
3342 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3343     QtDemuxStream ** stream, guint32 * default_sample_duration,
3344     guint32 * default_sample_size, guint32 * default_sample_flags,
3345     gint64 * base_offset)
3346 {
3347   guint32 flags = 0;
3348   guint32 track_id = 0;
3349
3350   if (!gst_byte_reader_skip (tfhd, 1) ||
3351       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3352     goto invalid_track;
3353
3354   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3355     goto invalid_track;
3356
3357   *stream = qtdemux_find_stream (qtdemux, track_id);
3358   if (G_UNLIKELY (!*stream))
3359     goto unknown_stream;
3360
3361   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3362     *base_offset = qtdemux->moof_offset;
3363
3364   if (flags & TF_BASE_DATA_OFFSET)
3365     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3366       goto invalid_track;
3367
3368   /* obtain stream defaults */
3369   qtdemux_parse_trex (qtdemux, *stream,
3370       default_sample_duration, default_sample_size, default_sample_flags);
3371
3372   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3373   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3374     if (!gst_byte_reader_skip (tfhd, 4))
3375       goto invalid_track;
3376
3377   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3378     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3379       goto invalid_track;
3380
3381   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3382     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3383       goto invalid_track;
3384
3385   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3386     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3387       goto invalid_track;
3388
3389   return TRUE;
3390
3391 invalid_track:
3392   {
3393     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3394     return FALSE;
3395   }
3396 unknown_stream:
3397   {
3398     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3399     return TRUE;
3400   }
3401 }
3402
3403 static gboolean
3404 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3405     guint64 * decode_time)
3406 {
3407   guint32 version = 0;
3408
3409   if (!gst_byte_reader_get_uint32_be (br, &version))
3410     return FALSE;
3411
3412   version >>= 24;
3413   if (version == 1) {
3414     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3415       goto failed;
3416   } else {
3417     guint32 dec_time = 0;
3418     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3419       goto failed;
3420     *decode_time = dec_time;
3421   }
3422
3423   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3424       *decode_time);
3425
3426   return TRUE;
3427
3428 failed:
3429   {
3430     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3431     return FALSE;
3432   }
3433 }
3434
3435 /* Returns a pointer to a GstStructure containing the properties of
3436  * the stream sample identified by @sample_index. The caller must unref
3437  * the returned object after use. Returns NULL if unsuccessful. */
3438 static GstStructure *
3439 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3440     QtDemuxStream * stream, guint sample_index)
3441 {
3442   QtDemuxCencSampleSetInfo *info = NULL;
3443
3444   g_return_val_if_fail (stream != NULL, NULL);
3445   g_return_val_if_fail (stream->protected, NULL);
3446   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3447
3448   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3449
3450   /* Currently, cenc properties for groups of samples are not supported, so
3451    * simply return a copy of the default sample properties */
3452   return gst_structure_copy (info->default_properties);
3453 }
3454
3455 /* Parses the sizes of sample auxiliary information contained within a stream,
3456  * as given in a saiz box. Returns array of sample_count guint8 size values,
3457  * or NULL on failure */
3458 static guint8 *
3459 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3460     GstByteReader * br, guint32 * sample_count)
3461 {
3462   guint32 flags = 0;
3463   guint8 *info_sizes;
3464   guint8 default_info_size;
3465
3466   g_return_val_if_fail (qtdemux != NULL, NULL);
3467   g_return_val_if_fail (stream != NULL, NULL);
3468   g_return_val_if_fail (br != NULL, NULL);
3469   g_return_val_if_fail (sample_count != NULL, NULL);
3470
3471   if (!gst_byte_reader_get_uint32_be (br, &flags))
3472     return NULL;
3473
3474   if (flags & 0x1) {
3475     /* aux_info_type and aux_info_type_parameter are ignored */
3476     if (!gst_byte_reader_skip (br, 8))
3477       return NULL;
3478   }
3479
3480   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3481     return NULL;
3482   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3483
3484   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3485     return NULL;
3486   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3487
3488
3489   if (default_info_size == 0) {
3490     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3491       return NULL;
3492     }
3493   } else {
3494     info_sizes = g_new (guint8, *sample_count);
3495     memset (info_sizes, default_info_size, *sample_count);
3496   }
3497
3498   return info_sizes;
3499 }
3500
3501 /* Parses the offset of sample auxiliary information contained within a stream,
3502  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3503 static gboolean
3504 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3505     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3506     guint64 * offset)
3507 {
3508   guint8 version = 0;
3509   guint32 flags = 0;
3510   guint32 aux_info_type = 0;
3511   guint32 aux_info_type_parameter = 0;
3512   guint32 entry_count;
3513   guint32 off_32;
3514   guint64 off_64;
3515   const guint8 *aux_info_type_data = NULL;
3516
3517   g_return_val_if_fail (qtdemux != NULL, FALSE);
3518   g_return_val_if_fail (stream != NULL, FALSE);
3519   g_return_val_if_fail (br != NULL, FALSE);
3520   g_return_val_if_fail (offset != NULL, FALSE);
3521
3522   if (!gst_byte_reader_get_uint8 (br, &version))
3523     return FALSE;
3524
3525   if (!gst_byte_reader_get_uint24_be (br, &flags))
3526     return FALSE;
3527
3528   if (flags & 0x1) {
3529
3530     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3531       return FALSE;
3532     aux_info_type = QT_FOURCC (aux_info_type_data);
3533
3534     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3535       return FALSE;
3536   } else if (stream->protected) {
3537     aux_info_type = stream->protection_scheme_type;
3538   } else {
3539     aux_info_type = stream->fourcc;
3540   }
3541
3542   if (info_type)
3543     *info_type = aux_info_type;
3544   if (info_type_parameter)
3545     *info_type_parameter = aux_info_type_parameter;
3546
3547   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3548       "aux_info_type_parameter:  %#06x",
3549       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3550
3551   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3552     return FALSE;
3553
3554   if (entry_count != 1) {
3555     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3556     return FALSE;
3557   }
3558
3559   if (version == 0) {
3560     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3561       return FALSE;
3562     *offset = (guint64) off_32;
3563   } else {
3564     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3565       return FALSE;
3566     *offset = off_64;
3567   }
3568
3569   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3570   return TRUE;
3571 }
3572
3573 static void
3574 qtdemux_gst_structure_free (GstStructure * gststructure)
3575 {
3576   if (gststructure) {
3577     gst_structure_free (gststructure);
3578   }
3579 }
3580
3581 /* Parses auxiliary information relating to samples protected using Common
3582  * Encryption (cenc); the format of this information is defined in
3583  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3584 static gboolean
3585 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3586     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3587 {
3588   QtDemuxCencSampleSetInfo *ss_info = NULL;
3589   guint8 size;
3590   gint i;
3591
3592   g_return_val_if_fail (qtdemux != NULL, FALSE);
3593   g_return_val_if_fail (stream != NULL, FALSE);
3594   g_return_val_if_fail (br != NULL, FALSE);
3595   g_return_val_if_fail (stream->protected, FALSE);
3596   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3597
3598   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3599
3600   if (ss_info->crypto_info) {
3601     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3602     g_ptr_array_free (ss_info->crypto_info, TRUE);
3603   }
3604
3605   ss_info->crypto_info =
3606       g_ptr_array_new_full (sample_count,
3607       (GDestroyNotify) qtdemux_gst_structure_free);
3608
3609   for (i = 0; i < sample_count; ++i) {
3610     GstStructure *properties;
3611     guint16 n_subsamples = 0;
3612     guint8 *data;
3613     guint iv_size;
3614     GstBuffer *buf;
3615
3616     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3617     if (properties == NULL) {
3618       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3619       return FALSE;
3620     }
3621     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3622       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3623       gst_structure_free (properties);
3624       return FALSE;
3625     }
3626     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3627       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3628       gst_structure_free (properties);
3629       return FALSE;
3630     }
3631     buf = gst_buffer_new_wrapped (data, iv_size);
3632     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3633     gst_buffer_unref (buf);
3634     size = info_sizes[i];
3635     if (size > iv_size) {
3636       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3637           || !(n_subsamples > 0)) {
3638         gst_structure_free (properties);
3639         GST_ERROR_OBJECT (qtdemux,
3640             "failed to get subsample count for sample %u", i);
3641         return FALSE;
3642       }
3643       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3644       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3645         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3646             i);
3647         gst_structure_free (properties);
3648         return FALSE;
3649       }
3650       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3651       if (!buf) {
3652         gst_structure_free (properties);
3653         return FALSE;
3654       }
3655       gst_structure_set (properties,
3656           "subsample_count", G_TYPE_UINT, n_subsamples,
3657           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3658       gst_buffer_unref (buf);
3659     } else {
3660       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3661     }
3662     g_ptr_array_add (ss_info->crypto_info, properties);
3663   }
3664   return TRUE;
3665 }
3666
3667 /* Converts a UUID in raw byte form to a string representation, as defined in
3668  * RFC 4122. The caller takes ownership of the returned string and is
3669  * responsible for freeing it after use. */
3670 static gchar *
3671 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3672 {
3673   const guint8 *uuid = (const guint8 *) uuid_bytes;
3674
3675   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3676       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3677       uuid[0], uuid[1], uuid[2], uuid[3],
3678       uuid[4], uuid[5], uuid[6], uuid[7],
3679       uuid[8], uuid[9], uuid[10], uuid[11],
3680       uuid[12], uuid[13], uuid[14], uuid[15]);
3681 }
3682
3683 /* Parses a Protection System Specific Header box (pssh), as defined in the
3684  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3685  * information needed by a specific content protection system in order to
3686  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3687  * otherwise. */
3688 static gboolean
3689 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3690 {
3691   gchar *sysid_string;
3692   guint32 pssh_size = QT_UINT32 (node->data);
3693   GstBuffer *pssh = NULL;
3694   GstEvent *event = NULL;
3695   guint32 parent_box_type;
3696   gint i;
3697
3698   if (G_UNLIKELY (pssh_size < 32U)) {
3699     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3700     return FALSE;
3701   }
3702
3703   sysid_string =
3704       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3705
3706   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3707
3708   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3709   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3710       gst_buffer_get_size (pssh));
3711
3712   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3713
3714   /* Push an event containing the pssh box onto the queues of all streams. */
3715   event = gst_event_new_protection (sysid_string, pssh,
3716       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3717   for (i = 0; i < qtdemux->n_streams; ++i) {
3718     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3719         gst_event_ref (event));
3720   }
3721   g_free (sysid_string);
3722   gst_event_unref (event);
3723   gst_buffer_unref (pssh);
3724   return TRUE;
3725 }
3726
3727 static gboolean
3728 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3729     guint64 moof_offset, QtDemuxStream * stream)
3730 {
3731   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3732   GNode *uuid_node;
3733   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3734   GNode *saiz_node, *saio_node, *pssh_node;
3735   GstByteReader saiz_data, saio_data;
3736   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3737   gint64 base_offset, running_offset;
3738   guint32 frag_num;
3739
3740   /* NOTE @stream ignored */
3741
3742   moof_node = g_node_new ((guint8 *) buffer);
3743   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3744   qtdemux_node_dump (qtdemux, moof_node);
3745
3746   /* Get fragment number from mfhd and check it's valid */
3747   mfhd_node =
3748       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3749   if (mfhd_node == NULL)
3750     goto missing_mfhd;
3751   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3752     goto fail;
3753   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3754
3755   /* unknown base_offset to start with */
3756   base_offset = running_offset = -1;
3757   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3758   while (traf_node) {
3759     guint64 decode_time = 0;
3760
3761     /* Fragment Header node */
3762     tfhd_node =
3763         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3764         &tfhd_data);
3765     if (!tfhd_node)
3766       goto missing_tfhd;
3767     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3768             &ds_size, &ds_flags, &base_offset))
3769       goto missing_tfhd;
3770
3771     /* The following code assumes at most a single set of sample auxiliary
3772      * data in the fragment (consisting of a saiz box and a corresponding saio
3773      * box); in theory, however, there could be multiple sets of sample
3774      * auxiliary data in a fragment. */
3775     saiz_node =
3776         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3777         &saiz_data);
3778     if (saiz_node) {
3779       guint32 info_type = 0;
3780       guint64 offset = 0;
3781       guint32 info_type_parameter = 0;
3782
3783       g_free (qtdemux->cenc_aux_info_sizes);
3784
3785       qtdemux->cenc_aux_info_sizes =
3786           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3787           &qtdemux->cenc_aux_sample_count);
3788       if (qtdemux->cenc_aux_info_sizes == NULL) {
3789         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3790         goto fail;
3791       }
3792       saio_node =
3793           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3794           &saio_data);
3795       if (!saio_node) {
3796         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3797         g_free (qtdemux->cenc_aux_info_sizes);
3798         qtdemux->cenc_aux_info_sizes = NULL;
3799         goto fail;
3800       }
3801
3802       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3803                   &info_type, &info_type_parameter, &offset))) {
3804         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3805         g_free (qtdemux->cenc_aux_info_sizes);
3806         qtdemux->cenc_aux_info_sizes = NULL;
3807         goto fail;
3808       }
3809       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3810         offset += (guint64) (base_offset - qtdemux->moof_offset);
3811       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3812         GstByteReader br;
3813         if (offset > length) {
3814           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3815           qtdemux->cenc_aux_info_offset = offset;
3816         } else {
3817           gst_byte_reader_init (&br, buffer + offset, length - offset);
3818           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3819                   qtdemux->cenc_aux_info_sizes,
3820                   qtdemux->cenc_aux_sample_count)) {
3821             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3822             g_free (qtdemux->cenc_aux_info_sizes);
3823             qtdemux->cenc_aux_info_sizes = NULL;
3824             goto fail;
3825           }
3826         }
3827       }
3828     }
3829
3830     tfdt_node =
3831         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3832         &tfdt_data);
3833     if (tfdt_node) {
3834       /* We'll use decode_time to interpolate timestamps
3835        * in case the input timestamps are missing */
3836       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3837
3838       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3839           " (%" GST_TIME_FORMAT ")", decode_time,
3840           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3841
3842       /* Discard the fragment buffer timestamp info to avoid using it.
3843        * Rely on tfdt instead as it is more accurate than the timestamp
3844        * that is fetched from a manifest/playlist and is usually
3845        * less accurate. */
3846       qtdemux->fragment_start = -1;
3847     }
3848
3849     if (G_UNLIKELY (!stream)) {
3850       /* we lost track of offset, we'll need to regain it,
3851        * but can delay complaining until later or avoid doing so altogether */
3852       base_offset = -2;
3853       goto next;
3854     }
3855     if (G_UNLIKELY (base_offset < -1))
3856       goto lost_offset;
3857
3858     if (qtdemux->upstream_format_is_time)
3859       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3860
3861     /* initialise moof sample data */
3862     stream->n_samples_moof = 0;
3863     stream->duration_last_moof = stream->duration_moof;
3864     stream->duration_moof = 0;
3865
3866     /* Track Run node */
3867     trun_node =
3868         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3869         &trun_data);
3870     while (trun_node) {
3871       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3872           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3873           &running_offset, decode_time);
3874       /* iterate all siblings */
3875       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3876           &trun_data);
3877     }
3878
3879     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3880     if (uuid_node) {
3881       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3882       guint32 box_length = QT_UINT32 (uuid_buffer);
3883
3884       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3885     }
3886
3887     /* if no new base_offset provided for next traf,
3888      * base is end of current traf */
3889     base_offset = running_offset;
3890     running_offset = -1;
3891
3892     if (stream->n_samples_moof && stream->duration_moof)
3893       stream->new_caps = TRUE;
3894
3895   next:
3896     /* iterate all siblings */
3897     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3898   }
3899
3900   /* parse any protection system info */
3901   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3902   while (pssh_node) {
3903     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3904     qtdemux_parse_pssh (qtdemux, pssh_node);
3905     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3906   }
3907
3908   g_node_destroy (moof_node);
3909   return TRUE;
3910
3911 missing_tfhd:
3912   {
3913     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3914     goto fail;
3915   }
3916 missing_mfhd:
3917   {
3918     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3919     goto fail;
3920   }
3921 lost_offset:
3922   {
3923     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3924     goto fail;
3925   }
3926 fail:
3927   {
3928     g_node_destroy (moof_node);
3929     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3930         (_("This file is corrupt and cannot be played.")), (NULL));
3931     return FALSE;
3932   }
3933 }
3934
3935 #if 0
3936 /* might be used if some day we actually use mfra & co
3937  * for random access to fragments,
3938  * but that will require quite some modifications and much less relying
3939  * on a sample array */
3940 #endif
3941
3942 static gboolean
3943 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3944 {
3945   QtDemuxStream *stream;
3946   guint32 ver_flags, track_id, len, num_entries, i;
3947   guint value_size, traf_size, trun_size, sample_size;
3948   guint64 time = 0, moof_offset = 0;
3949 #if 0
3950   GstBuffer *buf = NULL;
3951   GstFlowReturn ret;
3952 #endif
3953   GstByteReader tfra;
3954
3955   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3956
3957   if (!gst_byte_reader_skip (&tfra, 8))
3958     return FALSE;
3959
3960   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3961     return FALSE;
3962
3963   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3964       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3965       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3966     return FALSE;
3967
3968   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3969
3970   stream = qtdemux_find_stream (qtdemux, track_id);
3971   if (stream == NULL)
3972     goto unknown_trackid;
3973
3974   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3975   sample_size = (len & 3) + 1;
3976   trun_size = ((len & 12) >> 2) + 1;
3977   traf_size = ((len & 48) >> 4) + 1;
3978
3979   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3980       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3981
3982   if (num_entries == 0)
3983     goto no_samples;
3984
3985   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3986           value_size + value_size + traf_size + trun_size + sample_size))
3987     goto corrupt_file;
3988
3989   g_free (stream->ra_entries);
3990   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3991   stream->n_ra_entries = num_entries;
3992
3993   for (i = 0; i < num_entries; i++) {
3994     qt_atom_parser_get_offset (&tfra, value_size, &time);
3995     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3996     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3997     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3998     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3999
4000     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4001
4002     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4003         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4004
4005     stream->ra_entries[i].ts = time;
4006     stream->ra_entries[i].moof_offset = moof_offset;
4007
4008     /* don't want to go through the entire file and read all moofs at startup */
4009 #if 0
4010     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4011     if (ret != GST_FLOW_OK)
4012       goto corrupt_file;
4013     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4014         moof_offset, stream);
4015     gst_buffer_unref (buf);
4016 #endif
4017   }
4018
4019   check_update_duration (qtdemux, time);
4020
4021   return TRUE;
4022
4023 /* ERRORS */
4024 unknown_trackid:
4025   {
4026     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4027     return FALSE;
4028   }
4029 corrupt_file:
4030   {
4031     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4032     return FALSE;
4033   }
4034 no_samples:
4035   {
4036     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4037     return FALSE;
4038   }
4039 }
4040
4041 static gboolean
4042 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4043 {
4044   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4045   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4046   GstBuffer *mfro = NULL, *mfra = NULL;
4047   GstFlowReturn flow;
4048   gboolean ret = FALSE;
4049   GNode *mfra_node, *tfra_node;
4050   guint64 mfra_offset = 0;
4051   guint32 fourcc, mfra_size;
4052   gint64 len;
4053
4054   /* query upstream size in bytes */
4055   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4056     goto size_query_failed;
4057
4058   /* mfro box should be at the very end of the file */
4059   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4060   if (flow != GST_FLOW_OK)
4061     goto exit;
4062
4063   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4064
4065   fourcc = QT_FOURCC (mfro_map.data + 4);
4066   if (fourcc != FOURCC_mfro)
4067     goto exit;
4068
4069   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4070   if (mfro_map.size < 16)
4071     goto invalid_mfro_size;
4072
4073   mfra_size = QT_UINT32 (mfro_map.data + 12);
4074   if (mfra_size >= len)
4075     goto invalid_mfra_size;
4076
4077   mfra_offset = len - mfra_size;
4078
4079   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4080       mfra_offset, mfra_size);
4081
4082   /* now get and parse mfra box */
4083   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4084   if (flow != GST_FLOW_OK)
4085     goto broken_file;
4086
4087   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4088
4089   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4090   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4091
4092   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4093
4094   while (tfra_node) {
4095     qtdemux_parse_tfra (qtdemux, tfra_node);
4096     /* iterate all siblings */
4097     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4098   }
4099   g_node_destroy (mfra_node);
4100
4101   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4102   ret = TRUE;
4103
4104 exit:
4105
4106   if (mfro) {
4107     if (mfro_map.memory != NULL)
4108       gst_buffer_unmap (mfro, &mfro_map);
4109     gst_buffer_unref (mfro);
4110   }
4111   if (mfra) {
4112     if (mfra_map.memory != NULL)
4113       gst_buffer_unmap (mfra, &mfra_map);
4114     gst_buffer_unref (mfra);
4115   }
4116   return ret;
4117
4118 /* ERRORS */
4119 size_query_failed:
4120   {
4121     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4122     goto exit;
4123   }
4124 invalid_mfro_size:
4125   {
4126     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4127     goto exit;
4128   }
4129 invalid_mfra_size:
4130   {
4131     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4132     goto exit;
4133   }
4134 broken_file:
4135   {
4136     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4137     goto exit;
4138   }
4139 }
4140
4141 static guint64
4142 add_offset (guint64 offset, guint64 advance)
4143 {
4144   /* Avoid 64-bit overflow by clamping */
4145   if (offset > G_MAXUINT64 - advance)
4146     return G_MAXUINT64;
4147   return offset + advance;
4148 }
4149
4150 static GstFlowReturn
4151 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4152 {
4153   guint64 length = 0;
4154   guint32 fourcc = 0;
4155   GstBuffer *buf = NULL;
4156   GstFlowReturn ret = GST_FLOW_OK;
4157   guint64 cur_offset = qtdemux->offset;
4158   GstMapInfo map;
4159
4160   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4161   if (G_UNLIKELY (ret != GST_FLOW_OK))
4162     goto beach;
4163   gst_buffer_map (buf, &map, GST_MAP_READ);
4164   if (G_LIKELY (map.size >= 8))
4165     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4166   gst_buffer_unmap (buf, &map);
4167   gst_buffer_unref (buf);
4168
4169   /* maybe we already got most we needed, so only consider this eof */
4170   if (G_UNLIKELY (length == 0)) {
4171     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4172         (_("Invalid atom size.")),
4173         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4174             GST_FOURCC_ARGS (fourcc)));
4175     ret = GST_FLOW_EOS;
4176     goto beach;
4177   }
4178
4179   switch (fourcc) {
4180     case FOURCC_moof:
4181       /* record for later parsing when needed */
4182       if (!qtdemux->moof_offset) {
4183         qtdemux->moof_offset = qtdemux->offset;
4184       }
4185       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4186         /* FIXME */
4187       } else {
4188         qtdemux->offset += length;      /* skip moof and keep going */
4189       }
4190       if (qtdemux->got_moov) {
4191         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4192         ret = GST_FLOW_EOS;
4193         goto beach;
4194       }
4195       break;
4196     case FOURCC_mdat:
4197     case FOURCC_free:
4198     case FOURCC_wide:
4199     case FOURCC_PICT:
4200     case FOURCC_pnot:
4201     {
4202       GST_LOG_OBJECT (qtdemux,
4203           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4204           GST_FOURCC_ARGS (fourcc), cur_offset);
4205       qtdemux->offset = add_offset (qtdemux->offset, length);
4206       break;
4207     }
4208     case FOURCC_moov:
4209     {
4210       GstBuffer *moov = NULL;
4211
4212       if (qtdemux->got_moov) {
4213         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4214         qtdemux->offset = add_offset (qtdemux->offset, length);
4215         goto beach;
4216       }
4217
4218       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4219       if (ret != GST_FLOW_OK)
4220         goto beach;
4221       gst_buffer_map (moov, &map, GST_MAP_READ);
4222
4223       if (length != map.size) {
4224         /* Some files have a 'moov' atom at the end of the file which contains
4225          * a terminal 'free' atom where the body of the atom is missing.
4226          * Check for, and permit, this special case.
4227          */
4228         if (map.size >= 8) {
4229           guint8 *final_data = map.data + (map.size - 8);
4230           guint32 final_length = QT_UINT32 (final_data);
4231           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4232
4233           if (final_fourcc == FOURCC_free
4234               && map.size + final_length - 8 == length) {
4235             /* Ok, we've found that special case. Allocate a new buffer with
4236              * that free atom actually present. */
4237             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4238             gst_buffer_fill (newmoov, 0, map.data, map.size);
4239             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4240             gst_buffer_unmap (moov, &map);
4241             gst_buffer_unref (moov);
4242             moov = newmoov;
4243             gst_buffer_map (moov, &map, GST_MAP_READ);
4244           }
4245         }
4246       }
4247
4248       if (length != map.size) {
4249         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4250             (_("This file is incomplete and cannot be played.")),
4251             ("We got less than expected (received %" G_GSIZE_FORMAT
4252                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4253                 (guint) length, cur_offset));
4254         gst_buffer_unmap (moov, &map);
4255         gst_buffer_unref (moov);
4256         ret = GST_FLOW_ERROR;
4257         goto beach;
4258       }
4259       qtdemux->offset += length;
4260
4261       qtdemux_parse_moov (qtdemux, map.data, length);
4262       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4263
4264       qtdemux_parse_tree (qtdemux);
4265       if (qtdemux->moov_node_compressed) {
4266         g_node_destroy (qtdemux->moov_node_compressed);
4267         g_free (qtdemux->moov_node->data);
4268       }
4269       qtdemux->moov_node_compressed = NULL;
4270       g_node_destroy (qtdemux->moov_node);
4271       qtdemux->moov_node = NULL;
4272       gst_buffer_unmap (moov, &map);
4273       gst_buffer_unref (moov);
4274       qtdemux->got_moov = TRUE;
4275
4276       break;
4277     }
4278     case FOURCC_ftyp:
4279     {
4280       GstBuffer *ftyp = NULL;
4281
4282       /* extract major brand; might come in handy for ISO vs QT issues */
4283       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4284       if (ret != GST_FLOW_OK)
4285         goto beach;
4286       qtdemux->offset += length;
4287       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4288       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4289       gst_buffer_unmap (ftyp, &map);
4290       gst_buffer_unref (ftyp);
4291       break;
4292     }
4293     case FOURCC_uuid:
4294     {
4295       GstBuffer *uuid = NULL;
4296
4297       /* uuid are extension atoms */
4298       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4299       if (ret != GST_FLOW_OK)
4300         goto beach;
4301       qtdemux->offset += length;
4302       gst_buffer_map (uuid, &map, GST_MAP_READ);
4303       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4304       gst_buffer_unmap (uuid, &map);
4305       gst_buffer_unref (uuid);
4306       break;
4307     }
4308     case FOURCC_sidx:
4309     {
4310       GstBuffer *sidx = NULL;
4311       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4312       if (ret != GST_FLOW_OK)
4313         goto beach;
4314       qtdemux->offset += length;
4315       gst_buffer_map (sidx, &map, GST_MAP_READ);
4316       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4317       gst_buffer_unmap (sidx, &map);
4318       gst_buffer_unref (sidx);
4319       break;
4320     }
4321     default:
4322     {
4323       GstBuffer *unknown = NULL;
4324
4325       GST_LOG_OBJECT (qtdemux,
4326           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4327           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4328           cur_offset);
4329       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4330       if (ret != GST_FLOW_OK)
4331         goto beach;
4332       gst_buffer_map (unknown, &map, GST_MAP_READ);
4333       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4334       gst_buffer_unmap (unknown, &map);
4335       gst_buffer_unref (unknown);
4336       qtdemux->offset += length;
4337       break;
4338     }
4339   }
4340
4341 beach:
4342   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4343     /* digested all data, show what we have */
4344     qtdemux_prepare_streams (qtdemux);
4345     ret = qtdemux_expose_streams (qtdemux);
4346
4347     qtdemux->state = QTDEMUX_STATE_MOVIE;
4348     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4349         qtdemux->state);
4350     return ret;
4351   }
4352   return ret;
4353 }
4354
4355 /* Seeks to the previous keyframe of the indexed stream and
4356  * aligns other streams with respect to the keyframe timestamp
4357  * of indexed stream. Only called in case of Reverse Playback
4358  */
4359 static GstFlowReturn
4360 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4361 {
4362   guint8 n = 0;
4363   guint32 seg_idx = 0, k_index = 0;
4364   guint32 ref_seg_idx, ref_k_index;
4365   GstClockTime k_pos = 0, last_stop = 0;
4366   QtDemuxSegment *seg = NULL;
4367   QtDemuxStream *ref_str = NULL;
4368   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4369   guint64 target_ts;
4370
4371   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4372    * and finally align all the other streams on that timestamp with their
4373    * respective keyframes */
4374   for (n = 0; n < qtdemux->n_streams; n++) {
4375     QtDemuxStream *str = qtdemux->streams[n];
4376
4377     /* No candidate yet, take the first stream */
4378     if (!ref_str) {
4379       ref_str = str;
4380       continue;
4381     }
4382
4383     /* So that stream has a segment, we prefer video streams */
4384     if (str->subtype == FOURCC_vide) {
4385       ref_str = str;
4386       break;
4387     }
4388   }
4389
4390   if (G_UNLIKELY (!ref_str)) {
4391     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4392     goto eos;
4393   }
4394
4395   if (G_UNLIKELY (!ref_str->from_sample)) {
4396     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4397     goto eos;
4398   }
4399
4400   /* So that stream has been playing from from_sample to to_sample. We will
4401    * get the timestamp of the previous sample and search for a keyframe before
4402    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4403   if (ref_str->subtype == FOURCC_vide) {
4404     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4405         ref_str->from_sample - 1, FALSE);
4406   } else {
4407     if (ref_str->from_sample >= 10)
4408       k_index = ref_str->from_sample - 10;
4409     else
4410       k_index = 0;
4411   }
4412
4413   target_ts =
4414       ref_str->samples[k_index].timestamp +
4415       ref_str->samples[k_index].pts_offset;
4416
4417   /* get current segment for that stream */
4418   seg = &ref_str->segments[ref_str->segment_index];
4419   /* Use segment start in original timescale for comparisons */
4420   seg_media_start_mov = seg->trak_media_start;
4421
4422   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4423       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4424       k_index, target_ts, seg_media_start_mov,
4425       GST_TIME_ARGS (seg->media_start));
4426
4427   /* Crawl back through segments to find the one containing this I frame */
4428   while (target_ts < seg_media_start_mov) {
4429     GST_DEBUG_OBJECT (qtdemux,
4430         "keyframe position (sample %u) is out of segment %u " " target %"
4431         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4432         ref_str->segment_index, target_ts, seg_media_start_mov);
4433
4434     if (G_UNLIKELY (!ref_str->segment_index)) {
4435       /* Reached first segment, let's consider it's EOS */
4436       goto eos;
4437     }
4438     ref_str->segment_index--;
4439     seg = &ref_str->segments[ref_str->segment_index];
4440     /* Use segment start in original timescale for comparisons */
4441     seg_media_start_mov = seg->trak_media_start;
4442   }
4443   /* Calculate time position of the keyframe and where we should stop */
4444   k_pos =
4445       QTSTREAMTIME_TO_GSTTIME (ref_str,
4446       target_ts - seg->trak_media_start) + seg->time;
4447   last_stop =
4448       QTSTREAMTIME_TO_GSTTIME (ref_str,
4449       ref_str->samples[ref_str->from_sample].timestamp -
4450       seg->trak_media_start) + seg->time;
4451
4452   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4453       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4454       k_index, GST_TIME_ARGS (k_pos));
4455
4456   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4457   qtdemux->segment.position = last_stop;
4458   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4459       GST_TIME_ARGS (last_stop));
4460
4461   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4462     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4463     goto eos;
4464   }
4465
4466   ref_seg_idx = ref_str->segment_index;
4467   ref_k_index = k_index;
4468
4469   /* Align them all on this */
4470   for (n = 0; n < qtdemux->n_streams; n++) {
4471     guint32 index = 0;
4472     GstClockTime seg_time = 0;
4473     QtDemuxStream *str = qtdemux->streams[n];
4474
4475     /* aligning reference stream again might lead to backing up to yet another
4476      * keyframe (due to timestamp rounding issues),
4477      * potentially putting more load on downstream; so let's try to avoid */
4478     if (str == ref_str) {
4479       seg_idx = ref_seg_idx;
4480       seg = &str->segments[seg_idx];
4481       k_index = ref_k_index;
4482       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4483           "sample at index %d", n, ref_str->segment_index, k_index);
4484     } else {
4485       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4486       GST_DEBUG_OBJECT (qtdemux,
4487           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4488           seg_idx, GST_TIME_ARGS (k_pos));
4489
4490       /* get segment and time in the segment */
4491       seg = &str->segments[seg_idx];
4492       seg_time = k_pos - seg->time;
4493
4494       /* get the media time in the segment.
4495        * No adjustment for empty "filler" segments */
4496       if (seg->media_start != GST_CLOCK_TIME_NONE)
4497         seg_time += seg->media_start;
4498
4499       /* get the index of the sample with media time */
4500       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4501       GST_DEBUG_OBJECT (qtdemux,
4502           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4503           GST_TIME_ARGS (seg_time), index);
4504
4505       /* find previous keyframe */
4506       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4507     }
4508
4509     /* Remember until where we want to go */
4510     str->to_sample = str->from_sample - 1;
4511     /* Define our time position */
4512     target_ts =
4513         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4514     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4515     if (seg->media_start != GST_CLOCK_TIME_NONE)
4516       str->time_position -= seg->media_start;
4517
4518     /* Now seek back in time */
4519     gst_qtdemux_move_stream (qtdemux, str, k_index);
4520     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4521         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4522         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4523   }
4524
4525   return GST_FLOW_OK;
4526
4527 eos:
4528   return GST_FLOW_EOS;
4529 }
4530
4531 /*
4532  * Gets the current qt segment start, stop and position for the
4533  * given time offset. This is used in update_segment()
4534  */
4535 static void
4536 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4537     QtDemuxStream * stream, GstClockTime offset,
4538     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4539 {
4540   GstClockTime seg_time;
4541   GstClockTime start, stop, time;
4542   QtDemuxSegment *segment;
4543
4544   segment = &stream->segments[stream->segment_index];
4545
4546   /* get time in this segment */
4547   seg_time = (offset - segment->time) * segment->rate;
4548
4549   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4550       GST_TIME_ARGS (seg_time));
4551
4552   if (G_UNLIKELY (seg_time > segment->duration)) {
4553     GST_LOG_OBJECT (stream->pad,
4554         "seg_time > segment->duration %" GST_TIME_FORMAT,
4555         GST_TIME_ARGS (segment->duration));
4556     seg_time = segment->duration;
4557   }
4558
4559   /* qtdemux->segment.stop is in outside-time-realm, whereas
4560    * segment->media_stop is in track-time-realm.
4561    *
4562    * In order to compare the two, we need to bring segment.stop
4563    * into the track-time-realm
4564    *
4565    * FIXME - does this comment still hold? Don't see any conversion here */
4566
4567   stop = qtdemux->segment.stop;
4568   if (stop == GST_CLOCK_TIME_NONE)
4569     stop = qtdemux->segment.duration;
4570   if (stop == GST_CLOCK_TIME_NONE)
4571     stop = segment->media_stop;
4572   else
4573     stop =
4574         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4575
4576   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4577     start = segment->time + seg_time;
4578     time = offset;
4579     stop = start - seg_time + segment->duration;
4580   } else if (qtdemux->segment.rate >= 0) {
4581     start = MIN (segment->media_start + seg_time, stop);
4582     time = offset;
4583   } else {
4584     if (segment->media_start >= qtdemux->segment.start) {
4585       time = segment->time;
4586     } else {
4587       time = segment->time + (qtdemux->segment.start - segment->media_start);
4588     }
4589
4590     start = MAX (segment->media_start, qtdemux->segment.start);
4591     stop = MIN (segment->media_start + seg_time, stop);
4592   }
4593
4594   *_start = start;
4595   *_stop = stop;
4596   *_time = time;
4597 }
4598
4599 /*
4600  * Updates the qt segment used for the stream and pushes a new segment event
4601  * downstream on this stream's pad.
4602  */
4603 static gboolean
4604 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4605     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4606     GstClockTime * _stop)
4607 {
4608   QtDemuxSegment *segment;
4609   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4610   gdouble rate;
4611   GstEvent *event;
4612
4613   /* update the current segment */
4614   stream->segment_index = seg_idx;
4615
4616   /* get the segment */
4617   segment = &stream->segments[seg_idx];
4618
4619   if (G_UNLIKELY (offset < segment->time)) {
4620     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4621         GST_TIME_ARGS (segment->time));
4622     return FALSE;
4623   }
4624
4625   /* segment lies beyond total indicated duration */
4626   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4627           segment->time > qtdemux->segment.duration)) {
4628     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4629         " < segment->time %" GST_TIME_FORMAT,
4630         GST_TIME_ARGS (qtdemux->segment.duration),
4631         GST_TIME_ARGS (segment->time));
4632     return FALSE;
4633   }
4634
4635   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4636       &start, &stop, &time);
4637
4638   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4639       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4640       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4641
4642   /* combine global rate with that of the segment */
4643   rate = segment->rate * qtdemux->segment.rate;
4644
4645   /* Copy flags from main segment */
4646   stream->segment.flags = qtdemux->segment.flags;
4647
4648   /* update the segment values used for clipping */
4649   stream->segment.offset = qtdemux->segment.offset;
4650   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4651   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4652   stream->segment.rate = rate;
4653   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4654       stream->cslg_shift);
4655   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4656       stream->cslg_shift);
4657   stream->segment.time = time;
4658   stream->segment.position = stream->segment.start;
4659
4660   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4661       &stream->segment);
4662
4663   /* now prepare and send the segment */
4664   if (stream->pad) {
4665     event = gst_event_new_segment (&stream->segment);
4666     if (qtdemux->segment_seqnum) {
4667       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4668     }
4669     gst_pad_push_event (stream->pad, event);
4670     /* assume we can send more data now */
4671     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4672     /* clear to send tags on this pad now */
4673     gst_qtdemux_push_tags (qtdemux, stream);
4674   }
4675
4676   if (_start)
4677     *_start = start;
4678   if (_stop)
4679     *_stop = stop;
4680
4681   return TRUE;
4682 }
4683
4684 /* activate the given segment number @seg_idx of @stream at time @offset.
4685  * @offset is an absolute global position over all the segments.
4686  *
4687  * This will push out a NEWSEGMENT event with the right values and
4688  * position the stream index to the first decodable sample before
4689  * @offset.
4690  */
4691 static gboolean
4692 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4693     guint32 seg_idx, GstClockTime offset)
4694 {
4695   QtDemuxSegment *segment;
4696   guint32 index, kf_index;
4697   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4698
4699   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4700       seg_idx, GST_TIME_ARGS (offset));
4701
4702   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4703           &start, &stop))
4704     return FALSE;
4705
4706   segment = &stream->segments[stream->segment_index];
4707
4708   /* in the fragmented case, we pick a fragment that starts before our
4709    * desired position and rely on downstream to wait for a keyframe
4710    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4711    * tfra entries tells us which trun/sample the key unit is in, but we don't
4712    * make use of this additional information at the moment) */
4713   if (qtdemux->fragmented) {
4714     stream->to_sample = G_MAXUINT32;
4715     return TRUE;
4716   }
4717
4718   /* We don't need to look for a sample in push-based */
4719   if (!qtdemux->pullbased)
4720     return TRUE;
4721
4722   /* and move to the keyframe before the indicated media time of the
4723    * segment */
4724   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4725     if (qtdemux->segment.rate >= 0) {
4726       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4727       stream->to_sample = G_MAXUINT32;
4728       GST_DEBUG_OBJECT (stream->pad,
4729           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4730           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4731           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4732     } else {
4733       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4734       stream->to_sample = index;
4735       GST_DEBUG_OBJECT (stream->pad,
4736           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4737           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4738           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4739     }
4740   } else {
4741     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4742         "this is an empty segment");
4743     return TRUE;
4744   }
4745
4746   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4747    * encountered an error and printed a message so we return appropriately */
4748   if (index == -1)
4749     return FALSE;
4750
4751   /* we're at the right spot */
4752   if (index == stream->sample_index) {
4753     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4754     return TRUE;
4755   }
4756
4757   /* find keyframe of the target index */
4758   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4759
4760 /* *INDENT-OFF* */
4761 /* indent does stupid stuff with stream->samples[].timestamp */
4762
4763   /* if we move forwards, we don't have to go back to the previous
4764    * keyframe since we already sent that. We can also just jump to
4765    * the keyframe right before the target index if there is one. */
4766   if (index > stream->sample_index) {
4767     /* moving forwards check if we move past a keyframe */
4768     if (kf_index > stream->sample_index) {
4769       GST_DEBUG_OBJECT (stream->pad,
4770            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4771            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4772            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4773       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4774     } else {
4775       GST_DEBUG_OBJECT (stream->pad,
4776           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4777           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4778           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4779     }
4780   } else {
4781     GST_DEBUG_OBJECT (stream->pad,
4782         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4783         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4784         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4785     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4786   }
4787
4788 /* *INDENT-ON* */
4789
4790   return TRUE;
4791 }
4792
4793 /* prepare to get the current sample of @stream, getting essential values.
4794  *
4795  * This function will also prepare and send the segment when needed.
4796  *
4797  * Return FALSE if the stream is EOS.
4798  *
4799  * PULL-BASED
4800  */
4801 static gboolean
4802 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4803     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4804     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4805     gboolean * keyframe)
4806 {
4807   QtDemuxSample *sample;
4808   GstClockTime time_position;
4809   guint32 seg_idx;
4810
4811   g_return_val_if_fail (stream != NULL, FALSE);
4812
4813   time_position = stream->time_position;
4814   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4815     goto eos;
4816
4817   seg_idx = stream->segment_index;
4818   if (G_UNLIKELY (seg_idx == -1)) {
4819     /* find segment corresponding to time_position if we are looking
4820      * for a segment. */
4821     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4822   }
4823
4824   /* different segment, activate it, sample_index will be set. */
4825   if (G_UNLIKELY (stream->segment_index != seg_idx))
4826     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4827
4828   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4829                   segment_index]))) {
4830     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4831
4832     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4833         " prepare empty sample");
4834
4835     *empty = TRUE;
4836     *pts = *dts = time_position;
4837     *duration = seg->duration - (time_position - seg->time);
4838
4839     return TRUE;
4840   }
4841
4842   *empty = FALSE;
4843
4844   if (stream->sample_index == -1)
4845     stream->sample_index = 0;
4846
4847   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4848       stream->sample_index, stream->n_samples);
4849
4850   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4851     if (!qtdemux->fragmented)
4852       goto eos;
4853
4854     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4855     do {
4856       GstFlowReturn flow;
4857
4858       GST_OBJECT_LOCK (qtdemux);
4859       flow = qtdemux_add_fragmented_samples (qtdemux);
4860       GST_OBJECT_UNLOCK (qtdemux);
4861
4862       if (flow != GST_FLOW_OK)
4863         goto eos;
4864     }
4865     while (stream->sample_index >= stream->n_samples);
4866   }
4867
4868   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4869     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4870         stream->sample_index);
4871     return FALSE;
4872   }
4873
4874   /* now get the info for the sample we're at */
4875   sample = &stream->samples[stream->sample_index];
4876
4877   *dts = QTSAMPLE_DTS (stream, sample);
4878   *pts = QTSAMPLE_PTS (stream, sample);
4879   *offset = sample->offset;
4880   *size = sample->size;
4881   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4882   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4883
4884   return TRUE;
4885
4886   /* special cases */
4887 eos:
4888   {
4889     stream->time_position = GST_CLOCK_TIME_NONE;
4890     return FALSE;
4891   }
4892 }
4893
4894 /* move to the next sample in @stream.
4895  *
4896  * Moves to the next segment when needed.
4897  */
4898 static void
4899 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4900 {
4901   QtDemuxSample *sample;
4902   QtDemuxSegment *segment;
4903
4904   /* get current segment */
4905   segment = &stream->segments[stream->segment_index];
4906
4907   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4908     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4909     goto next_segment;
4910   }
4911
4912   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4913     /* Mark the stream as EOS */
4914     GST_DEBUG_OBJECT (qtdemux,
4915         "reached max allowed sample %u, mark EOS", stream->to_sample);
4916     stream->time_position = GST_CLOCK_TIME_NONE;
4917     return;
4918   }
4919
4920   /* move to next sample */
4921   stream->sample_index++;
4922   stream->offset_in_sample = 0;
4923
4924   /* reached the last sample, we need the next segment */
4925   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4926     goto next_segment;
4927
4928   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4929     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4930         stream->sample_index);
4931     return;
4932   }
4933
4934   /* get next sample */
4935   sample = &stream->samples[stream->sample_index];
4936
4937   /* see if we are past the segment */
4938   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4939     goto next_segment;
4940
4941   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4942     /* inside the segment, update time_position, looks very familiar to
4943      * GStreamer segments, doesn't it? */
4944     stream->time_position =
4945         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4946   } else {
4947     /* not yet in segment, time does not yet increment. This means
4948      * that we are still prerolling keyframes to the decoder so it can
4949      * decode the first sample of the segment. */
4950     stream->time_position = segment->time;
4951   }
4952   return;
4953
4954   /* move to the next segment */
4955 next_segment:
4956   {
4957     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4958
4959     if (stream->segment_index == stream->n_segments - 1) {
4960       /* are we at the end of the last segment, we're EOS */
4961       stream->time_position = GST_CLOCK_TIME_NONE;
4962     } else {
4963       /* else we're only at the end of the current segment */
4964       stream->time_position = segment->stop_time;
4965     }
4966     /* make sure we select a new segment */
4967
4968     /* accumulate previous segments */
4969     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4970       stream->accumulated_base +=
4971           (stream->segment.stop -
4972           stream->segment.start) / ABS (stream->segment.rate);
4973
4974     stream->segment_index = -1;
4975   }
4976 }
4977
4978 static void
4979 gst_qtdemux_sync_streams (GstQTDemux * demux)
4980 {
4981   gint i;
4982
4983   if (demux->n_streams <= 1)
4984     return;
4985
4986   for (i = 0; i < demux->n_streams; i++) {
4987     QtDemuxStream *stream;
4988     GstClockTime end_time;
4989
4990     stream = demux->streams[i];
4991
4992     if (!stream->pad)
4993       continue;
4994
4995     /* TODO advance time on subtitle streams here, if any some day */
4996
4997     /* some clips/trailers may have unbalanced streams at the end,
4998      * so send EOS on shorter stream to prevent stalling others */
4999
5000     /* do not mess with EOS if SEGMENT seeking */
5001     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5002       continue;
5003
5004     if (demux->pullbased) {
5005       /* loop mode is sample time based */
5006       if (!STREAM_IS_EOS (stream))
5007         continue;
5008     } else {
5009       /* push mode is byte position based */
5010       if (stream->n_samples &&
5011           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5012         continue;
5013     }
5014
5015     if (stream->sent_eos)
5016       continue;
5017
5018     /* only act if some gap */
5019     end_time = stream->segments[stream->n_segments - 1].stop_time;
5020     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5021         ", stream end: %" GST_TIME_FORMAT,
5022         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5023     if (GST_CLOCK_TIME_IS_VALID (end_time)
5024         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5025       GstEvent *event;
5026
5027       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5028           GST_PAD_NAME (stream->pad));
5029       stream->sent_eos = TRUE;
5030       event = gst_event_new_eos ();
5031       if (demux->segment_seqnum)
5032         gst_event_set_seqnum (event, demux->segment_seqnum);
5033       gst_pad_push_event (stream->pad, event);
5034     }
5035   }
5036 }
5037
5038 /* EOS and NOT_LINKED need to be combined. This means that we return:
5039  *
5040  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5041  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5042  */
5043 static GstFlowReturn
5044 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5045     GstFlowReturn ret)
5046 {
5047   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5048
5049   if (stream->pad)
5050     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5051         ret);
5052   else
5053     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5054
5055   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5056   return ret;
5057 }
5058
5059 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5060  * completely clipped
5061  *
5062  * Should be used only with raw buffers */
5063 static GstBuffer *
5064 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5065     GstBuffer * buf)
5066 {
5067   guint64 start, stop, cstart, cstop, diff;
5068   GstClockTime pts, duration;
5069   gsize size, osize;
5070   gint num_rate, denom_rate;
5071   gint frame_size;
5072   gboolean clip_data;
5073   guint offset;
5074
5075   osize = size = gst_buffer_get_size (buf);
5076   offset = 0;
5077
5078   /* depending on the type, setup the clip parameters */
5079   if (stream->subtype == FOURCC_soun) {
5080     frame_size = stream->bytes_per_frame;
5081     num_rate = GST_SECOND;
5082     denom_rate = (gint) stream->rate;
5083     clip_data = TRUE;
5084   } else if (stream->subtype == FOURCC_vide) {
5085     frame_size = size;
5086     num_rate = stream->fps_n;
5087     denom_rate = stream->fps_d;
5088     clip_data = FALSE;
5089   } else
5090     goto wrong_type;
5091
5092   if (frame_size <= 0)
5093     goto bad_frame_size;
5094
5095   /* we can only clip if we have a valid pts */
5096   pts = GST_BUFFER_PTS (buf);
5097   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5098     goto no_pts;
5099
5100   duration = GST_BUFFER_DURATION (buf);
5101
5102   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5103     duration =
5104         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5105   }
5106
5107   start = pts;
5108   stop = start + duration;
5109
5110   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5111               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5112     goto clipped;
5113
5114   /* see if some clipping happened */
5115   diff = cstart - start;
5116   if (diff > 0) {
5117     pts += diff;
5118     duration -= diff;
5119
5120     if (clip_data) {
5121       /* bring clipped time to samples and to bytes */
5122       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5123       diff *= frame_size;
5124
5125       GST_DEBUG_OBJECT (qtdemux,
5126           "clipping start to %" GST_TIME_FORMAT " %"
5127           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5128
5129       offset = diff;
5130       size -= diff;
5131     }
5132   }
5133   diff = stop - cstop;
5134   if (diff > 0) {
5135     duration -= diff;
5136
5137     if (clip_data) {
5138       /* bring clipped time to samples and then to bytes */
5139       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5140       diff *= frame_size;
5141       GST_DEBUG_OBJECT (qtdemux,
5142           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5143           " bytes", GST_TIME_ARGS (cstop), diff);
5144       size -= diff;
5145     }
5146   }
5147
5148   if (offset != 0 || size != osize)
5149     gst_buffer_resize (buf, offset, size);
5150
5151   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5152   GST_BUFFER_PTS (buf) = pts;
5153   GST_BUFFER_DURATION (buf) = duration;
5154
5155   return buf;
5156
5157   /* dropped buffer */
5158 wrong_type:
5159   {
5160     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5161     return buf;
5162   }
5163 bad_frame_size:
5164   {
5165     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5166     return buf;
5167   }
5168 no_pts:
5169   {
5170     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5171     return buf;
5172   }
5173 clipped:
5174   {
5175     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5176     gst_buffer_unref (buf);
5177     return NULL;
5178   }
5179 }
5180
5181 static GstBuffer *
5182 gst_qtdemux_align_buffer (GstQTDemux * demux,
5183     GstBuffer * buffer, gsize alignment)
5184 {
5185   GstMapInfo map;
5186
5187   gst_buffer_map (buffer, &map, GST_MAP_READ);
5188
5189   if (map.size < sizeof (guintptr)) {
5190     gst_buffer_unmap (buffer, &map);
5191     return buffer;
5192   }
5193
5194   if (((guintptr) map.data) & (alignment - 1)) {
5195     GstBuffer *new_buffer;
5196     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5197
5198     new_buffer = gst_buffer_new_allocate (NULL,
5199         gst_buffer_get_size (buffer), &params);
5200
5201     /* Copy data "by hand", so ensure alignment is kept: */
5202     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5203
5204     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5205     GST_DEBUG_OBJECT (demux,
5206         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5207         alignment);
5208
5209     gst_buffer_unmap (buffer, &map);
5210     gst_buffer_unref (buffer);
5211
5212     return new_buffer;
5213   }
5214
5215   gst_buffer_unmap (buffer, &map);
5216   return buffer;
5217 }
5218
5219 /* the input buffer metadata must be writable,
5220  * but time/duration etc not yet set and need not be preserved */
5221 static GstBuffer *
5222 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5223     GstBuffer * buf)
5224 {
5225   GstMapInfo map;
5226   guint nsize = 0;
5227   gchar *str;
5228
5229   /* not many cases for now */
5230   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
5231     /* send a one time dvd clut event */
5232     if (stream->pending_event && stream->pad)
5233       gst_pad_push_event (stream->pad, stream->pending_event);
5234     stream->pending_event = NULL;
5235   }
5236
5237   if (G_UNLIKELY (stream->subtype != FOURCC_text
5238           && stream->subtype != FOURCC_sbtl &&
5239           stream->subtype != FOURCC_subp)) {
5240     return buf;
5241   }
5242
5243   gst_buffer_map (buf, &map, GST_MAP_READ);
5244
5245   /* empty buffer is sent to terminate previous subtitle */
5246   if (map.size <= 2) {
5247     gst_buffer_unmap (buf, &map);
5248     gst_buffer_unref (buf);
5249     return NULL;
5250   }
5251   if (stream->subtype == FOURCC_subp) {
5252     /* That's all the processing needed for subpictures */
5253     gst_buffer_unmap (buf, &map);
5254     return buf;
5255   }
5256
5257   nsize = GST_READ_UINT16_BE (map.data);
5258   nsize = MIN (nsize, map.size - 2);
5259
5260   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5261       nsize, map.size);
5262
5263   /* takes care of UTF-8 validation or UTF-16 recognition,
5264    * no other encoding expected */
5265   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5266   gst_buffer_unmap (buf, &map);
5267   if (str) {
5268     gst_buffer_unref (buf);
5269     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5270   } else {
5271     /* this should not really happen unless the subtitle is corrupted */
5272     gst_buffer_unref (buf);
5273     buf = NULL;
5274   }
5275
5276   /* FIXME ? convert optional subsequent style info to markup */
5277
5278   return buf;
5279 }
5280
5281 /* Sets a buffer's attributes properly and pushes it downstream.
5282  * Also checks for additional actions and custom processing that may
5283  * need to be done first.
5284  */
5285 static GstFlowReturn
5286 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5287     QtDemuxStream * stream, GstBuffer * buf,
5288     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5289     gboolean keyframe, GstClockTime position, guint64 byte_position)
5290 {
5291   GstFlowReturn ret = GST_FLOW_OK;
5292
5293   /* offset the timestamps according to the edit list */
5294
5295   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
5296     gchar *url;
5297     GstMapInfo map;
5298
5299     gst_buffer_map (buf, &map, GST_MAP_READ);
5300     url = g_strndup ((gchar *) map.data, map.size);
5301     gst_buffer_unmap (buf, &map);
5302     if (url != NULL && strlen (url) != 0) {
5303       /* we have RTSP redirect now */
5304       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5305           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5306               gst_structure_new ("redirect",
5307                   "new-location", G_TYPE_STRING, url, NULL)));
5308       qtdemux->posted_redirect = TRUE;
5309     } else {
5310       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5311           "posting");
5312     }
5313     g_free (url);
5314   }
5315
5316   /* position reporting */
5317   if (qtdemux->segment.rate >= 0) {
5318     qtdemux->segment.position = position;
5319     gst_qtdemux_sync_streams (qtdemux);
5320   }
5321
5322   if (G_UNLIKELY (!stream->pad)) {
5323     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5324     gst_buffer_unref (buf);
5325     goto exit;
5326   }
5327
5328   /* send out pending buffers */
5329   while (stream->buffers) {
5330     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5331
5332     if (G_UNLIKELY (stream->discont)) {
5333       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5334       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5335       stream->discont = FALSE;
5336     } else {
5337       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5338     }
5339
5340     if (stream->alignment > 1)
5341       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5342     gst_pad_push (stream->pad, buffer);
5343
5344     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5345   }
5346
5347   /* we're going to modify the metadata */
5348   buf = gst_buffer_make_writable (buf);
5349
5350   if (G_UNLIKELY (stream->need_process))
5351     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5352
5353   if (!buf) {
5354     goto exit;
5355   }
5356
5357   GST_BUFFER_DTS (buf) = dts;
5358   GST_BUFFER_PTS (buf) = pts;
5359   GST_BUFFER_DURATION (buf) = duration;
5360   GST_BUFFER_OFFSET (buf) = -1;
5361   GST_BUFFER_OFFSET_END (buf) = -1;
5362
5363   if (G_UNLIKELY (stream->rgb8_palette))
5364     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
5365
5366   if (G_UNLIKELY (stream->padding)) {
5367     gst_buffer_resize (buf, stream->padding, -1);
5368   }
5369 #if 0
5370   if (G_UNLIKELY (qtdemux->element_index)) {
5371     GstClockTime stream_time;
5372
5373     stream_time =
5374         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5375         timestamp);
5376     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5377       GST_LOG_OBJECT (qtdemux,
5378           "adding association %" GST_TIME_FORMAT "-> %"
5379           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5380       gst_index_add_association (qtdemux->element_index,
5381           qtdemux->index_id,
5382           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5383           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5384           GST_FORMAT_BYTES, byte_position, NULL);
5385     }
5386   }
5387 #endif
5388
5389   if (stream->need_clip)
5390     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5391
5392   if (G_UNLIKELY (buf == NULL))
5393     goto exit;
5394
5395   if (G_UNLIKELY (stream->discont)) {
5396     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5397     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5398     stream->discont = FALSE;
5399   } else {
5400     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5401   }
5402
5403   if (!keyframe) {
5404     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5405     stream->on_keyframe = FALSE;
5406   } else {
5407     stream->on_keyframe = TRUE;
5408   }
5409
5410
5411   GST_LOG_OBJECT (qtdemux,
5412       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5413       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5414       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5415       GST_PAD_NAME (stream->pad));
5416
5417   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5418     GstStructure *crypto_info;
5419     QtDemuxCencSampleSetInfo *info =
5420         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5421     gint index;
5422     GstEvent *event;
5423
5424     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5425       gst_pad_push_event (stream->pad, event);
5426     }
5427
5428     if (info->crypto_info == NULL) {
5429       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5430       gst_buffer_unref (buf);
5431       goto exit;
5432     }
5433
5434     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
5435     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5436       /* steal structure from array */
5437       crypto_info = g_ptr_array_index (info->crypto_info, index);
5438       g_ptr_array_index (info->crypto_info, index) = NULL;
5439       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
5440       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5441         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5442     }
5443   }
5444
5445   if (stream->alignment > 1)
5446     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5447
5448   ret = gst_pad_push (stream->pad, buf);
5449
5450   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5451     /* mark position in stream, we'll need this to know when to send GAP event */
5452     stream->segment.position = pts + duration;
5453   }
5454
5455 exit:
5456   return ret;
5457 }
5458
5459 static const QtDemuxRandomAccessEntry *
5460 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5461     GstClockTime pos, gboolean after)
5462 {
5463   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5464   guint n_entries = stream->n_ra_entries;
5465   guint i;
5466
5467   /* we assume the table is sorted */
5468   for (i = 0; i < n_entries; ++i) {
5469     if (entries[i].ts > pos)
5470       break;
5471   }
5472
5473   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5474    * probably okay to assume that the index lists the very first fragment */
5475   if (i == 0)
5476     return &entries[0];
5477
5478   if (after)
5479     return &entries[i];
5480   else
5481     return &entries[i - 1];
5482 }
5483
5484 static gboolean
5485 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5486 {
5487   const QtDemuxRandomAccessEntry *best_entry = NULL;
5488   guint i;
5489
5490   GST_OBJECT_LOCK (qtdemux);
5491
5492   g_assert (qtdemux->n_streams > 0);
5493
5494   for (i = 0; i < qtdemux->n_streams; i++) {
5495     const QtDemuxRandomAccessEntry *entry;
5496     QtDemuxStream *stream;
5497     gboolean is_audio_or_video;
5498
5499     stream = qtdemux->streams[i];
5500
5501     g_free (stream->samples);
5502     stream->samples = NULL;
5503     stream->n_samples = 0;
5504     stream->stbl_index = -1;    /* no samples have yet been parsed */
5505     stream->sample_index = -1;
5506
5507     if (stream->ra_entries == NULL)
5508       continue;
5509
5510     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5511       is_audio_or_video = TRUE;
5512     else
5513       is_audio_or_video = FALSE;
5514
5515     entry =
5516         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5517         stream->time_position, !is_audio_or_video);
5518
5519     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5520         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5521
5522     stream->pending_seek = entry;
5523
5524     /* decide position to jump to just based on audio/video tracks, not subs */
5525     if (!is_audio_or_video)
5526       continue;
5527
5528     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5529       best_entry = entry;
5530   }
5531
5532   if (best_entry == NULL) {
5533     GST_OBJECT_UNLOCK (qtdemux);
5534     return FALSE;
5535   }
5536
5537   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5538       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5539       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5540       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5541
5542   qtdemux->moof_offset = best_entry->moof_offset;
5543
5544   qtdemux_add_fragmented_samples (qtdemux);
5545
5546   GST_OBJECT_UNLOCK (qtdemux);
5547   return TRUE;
5548 }
5549
5550 static GstFlowReturn
5551 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5552 {
5553   GstFlowReturn ret = GST_FLOW_OK;
5554   GstBuffer *buf = NULL;
5555   QtDemuxStream *stream;
5556   GstClockTime min_time;
5557   guint64 offset = 0;
5558   GstClockTime dts = GST_CLOCK_TIME_NONE;
5559   GstClockTime pts = GST_CLOCK_TIME_NONE;
5560   GstClockTime duration = 0;
5561   gboolean keyframe = FALSE;
5562   guint sample_size = 0;
5563   gboolean empty = 0;
5564   guint size;
5565   gint index;
5566   gint i;
5567
5568   gst_qtdemux_push_pending_newsegment (qtdemux);
5569
5570   if (qtdemux->fragmented_seek_pending) {
5571     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5572     gst_qtdemux_do_fragmented_seek (qtdemux);
5573     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5574     qtdemux->fragmented_seek_pending = FALSE;
5575   }
5576
5577   /* Figure out the next stream sample to output, min_time is expressed in
5578    * global time and runs over the edit list segments. */
5579   min_time = G_MAXUINT64;
5580   index = -1;
5581   for (i = 0; i < qtdemux->n_streams; i++) {
5582     GstClockTime position;
5583
5584     stream = qtdemux->streams[i];
5585     position = stream->time_position;
5586
5587     /* position of -1 is EOS */
5588     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5589       min_time = position;
5590       index = i;
5591     }
5592   }
5593   /* all are EOS */
5594   if (G_UNLIKELY (index == -1)) {
5595     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5596     goto eos;
5597   }
5598
5599   /* check for segment end */
5600   if (G_UNLIKELY (qtdemux->segment.stop != -1
5601           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5602               || (qtdemux->segment.rate < 0
5603                   && qtdemux->segment.start > min_time))
5604           && qtdemux->streams[index]->on_keyframe)) {
5605     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5606     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5607     goto eos_stream;
5608   }
5609
5610   /* gap events for subtitle streams */
5611   for (i = 0; i < qtdemux->n_streams; i++) {
5612     stream = qtdemux->streams[i];
5613     if (stream->pad && (stream->subtype == FOURCC_subp
5614             || stream->subtype == FOURCC_text
5615             || stream->subtype == FOURCC_sbtl)) {
5616       /* send one second gap events until the stream catches up */
5617       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5618       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5619           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5620           stream->segment.position + GST_SECOND < min_time) {
5621         GstEvent *gap =
5622             gst_event_new_gap (stream->segment.position, GST_SECOND);
5623         gst_pad_push_event (stream->pad, gap);
5624         stream->segment.position += GST_SECOND;
5625       }
5626     }
5627   }
5628
5629   stream = qtdemux->streams[index];
5630   if (stream->new_caps) {
5631     gst_qtdemux_configure_stream (qtdemux, stream);
5632     qtdemux_do_allocation (qtdemux, stream);
5633   }
5634
5635   /* fetch info for the current sample of this stream */
5636   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5637               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5638     goto eos_stream;
5639
5640   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5641   if (G_UNLIKELY (qtdemux->
5642           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5643     if (stream->subtype == FOURCC_vide && !keyframe) {
5644       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5645       goto next;
5646     }
5647   }
5648
5649   GST_DEBUG_OBJECT (qtdemux,
5650       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5651       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5652       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5653       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5654
5655   if (G_UNLIKELY (empty)) {
5656     /* empty segment, push a gap and move to the next one */
5657     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5658     stream->segment.position = pts + duration;
5659     goto next;
5660   }
5661
5662   /* hmm, empty sample, skip and move to next sample */
5663   if (G_UNLIKELY (sample_size <= 0))
5664     goto next;
5665
5666   /* last pushed sample was out of boundary, goto next sample */
5667   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5668     goto next;
5669
5670   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5671     size = sample_size;
5672   } else {
5673     GST_DEBUG_OBJECT (qtdemux,
5674         "size %d larger than stream max_buffer_size %d, trimming",
5675         sample_size, stream->max_buffer_size);
5676     size =
5677         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5678   }
5679
5680   if (qtdemux->cenc_aux_info_offset > 0) {
5681     GstMapInfo map;
5682     GstByteReader br;
5683     GstBuffer *aux_info = NULL;
5684
5685     /* pull the data stored before the sample */
5686     ret =
5687         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5688         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5689     if (G_UNLIKELY (ret != GST_FLOW_OK))
5690       goto beach;
5691     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5692     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5693     gst_byte_reader_init (&br, map.data + 8, map.size);
5694     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5695             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5696       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5697       gst_buffer_unmap (aux_info, &map);
5698       gst_buffer_unref (aux_info);
5699       ret = GST_FLOW_ERROR;
5700       goto beach;
5701     }
5702     gst_buffer_unmap (aux_info, &map);
5703     gst_buffer_unref (aux_info);
5704   }
5705
5706   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5707       offset);
5708
5709   if (stream->use_allocator) {
5710     /* if we have a per-stream allocator, use it */
5711     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5712   }
5713
5714   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5715       size, &buf);
5716   if (G_UNLIKELY (ret != GST_FLOW_OK))
5717     goto beach;
5718
5719   if (size != sample_size) {
5720     pts += gst_util_uint64_scale_int (GST_SECOND,
5721         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5722     dts += gst_util_uint64_scale_int (GST_SECOND,
5723         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5724     duration = gst_util_uint64_scale_int (GST_SECOND,
5725         size / stream->bytes_per_frame, stream->timescale);
5726   }
5727
5728   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5729       dts, pts, duration, keyframe, min_time, offset);
5730
5731   if (size != sample_size) {
5732     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5733     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5734
5735     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5736         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5737     if (time_position >= segment->media_start) {
5738       /* inside the segment, update time_position, looks very familiar to
5739        * GStreamer segments, doesn't it? */
5740       stream->time_position = (time_position - segment->media_start) +
5741           segment->time;
5742     } else {
5743       /* not yet in segment, time does not yet increment. This means
5744        * that we are still prerolling keyframes to the decoder so it can
5745        * decode the first sample of the segment. */
5746       stream->time_position = segment->time;
5747     }
5748   }
5749
5750   /* combine flows */
5751   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5752   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5753    * we have no more data for the pad to push */
5754   if (ret == GST_FLOW_EOS)
5755     ret = GST_FLOW_OK;
5756
5757   stream->offset_in_sample += size;
5758   if (stream->offset_in_sample >= sample_size) {
5759     gst_qtdemux_advance_sample (qtdemux, stream);
5760   }
5761   goto beach;
5762
5763 next:
5764   gst_qtdemux_advance_sample (qtdemux, stream);
5765
5766 beach:
5767   return ret;
5768
5769   /* special cases */
5770 eos:
5771   {
5772     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5773     ret = GST_FLOW_EOS;
5774     goto beach;
5775   }
5776 eos_stream:
5777   {
5778     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5779     /* EOS will be raised if all are EOS */
5780     ret = GST_FLOW_OK;
5781     goto beach;
5782   }
5783 }
5784
5785 static void
5786 gst_qtdemux_loop (GstPad * pad)
5787 {
5788   GstQTDemux *qtdemux;
5789   guint64 cur_offset;
5790   GstFlowReturn ret;
5791
5792   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5793
5794   cur_offset = qtdemux->offset;
5795   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5796       cur_offset, qt_demux_state_string (qtdemux->state));
5797
5798   switch (qtdemux->state) {
5799     case QTDEMUX_STATE_INITIAL:
5800     case QTDEMUX_STATE_HEADER:
5801       ret = gst_qtdemux_loop_state_header (qtdemux);
5802       break;
5803     case QTDEMUX_STATE_MOVIE:
5804       ret = gst_qtdemux_loop_state_movie (qtdemux);
5805       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5806         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5807       }
5808       break;
5809     default:
5810       /* ouch */
5811       goto invalid_state;
5812   }
5813
5814   /* if something went wrong, pause */
5815   if (ret != GST_FLOW_OK)
5816     goto pause;
5817
5818 done:
5819   gst_object_unref (qtdemux);
5820   return;
5821
5822   /* ERRORS */
5823 invalid_state:
5824   {
5825     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5826         (NULL), ("streaming stopped, invalid state"));
5827     gst_pad_pause_task (pad);
5828     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5829     goto done;
5830   }
5831 pause:
5832   {
5833     const gchar *reason = gst_flow_get_name (ret);
5834
5835     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5836
5837     gst_pad_pause_task (pad);
5838
5839     /* fatal errors need special actions */
5840     /* check EOS */
5841     if (ret == GST_FLOW_EOS) {
5842       if (qtdemux->n_streams == 0) {
5843         /* we have no streams, post an error */
5844         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5845       }
5846       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5847         gint64 stop;
5848
5849         if ((stop = qtdemux->segment.stop) == -1)
5850           stop = qtdemux->segment.duration;
5851
5852         if (qtdemux->segment.rate >= 0) {
5853           GstMessage *message;
5854           GstEvent *event;
5855
5856           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5857           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5858               GST_FORMAT_TIME, stop);
5859           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5860           if (qtdemux->segment_seqnum) {
5861             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5862             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5863           }
5864           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5865           gst_qtdemux_push_event (qtdemux, event);
5866         } else {
5867           GstMessage *message;
5868           GstEvent *event;
5869
5870           /*  For Reverse Playback */
5871           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5872           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5873               GST_FORMAT_TIME, qtdemux->segment.start);
5874           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5875               qtdemux->segment.start);
5876           if (qtdemux->segment_seqnum) {
5877             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5878             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5879           }
5880           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5881           gst_qtdemux_push_event (qtdemux, event);
5882         }
5883       } else {
5884         GstEvent *event;
5885
5886         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5887         event = gst_event_new_eos ();
5888         if (qtdemux->segment_seqnum)
5889           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5890         gst_qtdemux_push_event (qtdemux, event);
5891       }
5892     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5893       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
5894       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5895     }
5896     goto done;
5897   }
5898 }
5899
5900 /*
5901  * has_next_entry
5902  *
5903  * Returns if there are samples to be played.
5904  */
5905 static gboolean
5906 has_next_entry (GstQTDemux * demux)
5907 {
5908   QtDemuxStream *stream;
5909   int i;
5910
5911   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5912
5913   for (i = 0; i < demux->n_streams; i++) {
5914     stream = demux->streams[i];
5915
5916     if (stream->sample_index == -1) {
5917       stream->sample_index = 0;
5918       stream->offset_in_sample = 0;
5919     }
5920
5921     if (stream->sample_index >= stream->n_samples) {
5922       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5923       continue;
5924     }
5925     GST_DEBUG_OBJECT (demux, "Found a sample");
5926     return TRUE;
5927   }
5928
5929   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5930   return FALSE;
5931 }
5932
5933 /*
5934  * next_entry_size
5935  *
5936  * Returns the size of the first entry at the current offset.
5937  * If -1, there are none (which means EOS or empty file).
5938  */
5939 static guint64
5940 next_entry_size (GstQTDemux * demux)
5941 {
5942   QtDemuxStream *stream;
5943   int i;
5944   int smallidx = -1;
5945   guint64 smalloffs = (guint64) - 1;
5946   QtDemuxSample *sample;
5947
5948   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5949       demux->offset);
5950
5951   for (i = 0; i < demux->n_streams; i++) {
5952     stream = demux->streams[i];
5953
5954     if (stream->sample_index == -1) {
5955       stream->sample_index = 0;
5956       stream->offset_in_sample = 0;
5957     }
5958
5959     if (stream->sample_index >= stream->n_samples) {
5960       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5961       continue;
5962     }
5963
5964     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5965       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5966           stream->sample_index);
5967       return -1;
5968     }
5969
5970     sample = &stream->samples[stream->sample_index];
5971
5972     GST_LOG_OBJECT (demux,
5973         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5974         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5975         sample->offset, sample->size);
5976
5977     if (((smalloffs == -1)
5978             || (sample->offset < smalloffs)) && (sample->size)) {
5979       smallidx = i;
5980       smalloffs = sample->offset;
5981     }
5982   }
5983
5984   GST_LOG_OBJECT (demux,
5985       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5986       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5987
5988   if (smallidx == -1)
5989     return -1;
5990
5991   stream = demux->streams[smallidx];
5992   sample = &stream->samples[stream->sample_index];
5993
5994   if (sample->offset >= demux->offset) {
5995     demux->todrop = sample->offset - demux->offset;
5996     return sample->size + demux->todrop;
5997   }
5998
5999   GST_DEBUG_OBJECT (demux,
6000       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6001   return -1;
6002 }
6003
6004 static void
6005 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6006 {
6007   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6008
6009   gst_element_post_message (GST_ELEMENT_CAST (demux),
6010       gst_message_new_element (GST_OBJECT_CAST (demux),
6011           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6012 }
6013
6014 static gboolean
6015 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6016 {
6017   GstEvent *event;
6018   gboolean res = 0;
6019
6020   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6021
6022   event =
6023       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6024       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6025       GST_SEEK_TYPE_NONE, -1);
6026
6027   /* store seqnum to drop flush events, they don't need to reach downstream */
6028   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6029   res = gst_pad_push_event (demux->sinkpad, event);
6030   demux->offset_seek_seqnum = 0;
6031
6032   return res;
6033 }
6034
6035 /* check for seekable upstream, above and beyond a mere query */
6036 static void
6037 gst_qtdemux_check_seekability (GstQTDemux * demux)
6038 {
6039   GstQuery *query;
6040   gboolean seekable = FALSE;
6041   gint64 start = -1, stop = -1;
6042
6043   if (demux->upstream_size)
6044     return;
6045
6046   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6047   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6048     GST_DEBUG_OBJECT (demux, "seeking query failed");
6049     goto done;
6050   }
6051
6052   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6053
6054   /* try harder to query upstream size if we didn't get it the first time */
6055   if (seekable && stop == -1) {
6056     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6057     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6058   }
6059
6060   /* if upstream doesn't know the size, it's likely that it's not seekable in
6061    * practice even if it technically may be seekable */
6062   if (seekable && (start != 0 || stop <= start)) {
6063     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6064     seekable = FALSE;
6065   }
6066
6067 done:
6068   gst_query_unref (query);
6069
6070   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6071       G_GUINT64_FORMAT ")", seekable, start, stop);
6072   demux->upstream_seekable = seekable;
6073   demux->upstream_size = seekable ? stop : -1;
6074 }
6075
6076 static void
6077 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6078 {
6079   g_return_if_fail (bytes <= demux->todrop);
6080
6081   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6082   gst_adapter_flush (demux->adapter, bytes);
6083   demux->neededbytes -= bytes;
6084   demux->offset += bytes;
6085   demux->todrop -= bytes;
6086 }
6087
6088 static void
6089 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6090 {
6091   if (G_UNLIKELY (demux->pending_newsegment)) {
6092     gint i;
6093
6094     gst_qtdemux_push_pending_newsegment (demux);
6095     /* clear to send tags on all streams */
6096     for (i = 0; i < demux->n_streams; i++) {
6097       QtDemuxStream *stream;
6098       stream = demux->streams[i];
6099       gst_qtdemux_push_tags (demux, stream);
6100       if (stream->sparse) {
6101         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6102         gst_pad_push_event (stream->pad,
6103             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6104       }
6105     }
6106   }
6107 }
6108
6109 static void
6110 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6111     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6112 {
6113   GstClockTime ts, dur;
6114   GstEvent *gap;
6115
6116   ts = pos;
6117   dur =
6118       stream->segments[segment_index].duration - (pos -
6119       stream->segments[segment_index].time);
6120   gap = gst_event_new_gap (ts, dur);
6121   stream->time_position += dur;
6122
6123   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6124       "segment: %" GST_PTR_FORMAT, gap);
6125   gst_pad_push_event (stream->pad, gap);
6126 }
6127
6128 static void
6129 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6130     QtDemuxStream * stream)
6131 {
6132   gint i;
6133
6134   /* Push any initial gap segments before proceeding to the
6135    * 'real' data */
6136   for (i = 0; i < stream->n_segments; i++) {
6137     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6138
6139     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6140       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6141           stream->time_position);
6142     } else {
6143       /* Only support empty segment at the beginning followed by
6144        * one non-empty segment, this was checked when parsing the
6145        * edts atom, arriving here is unexpected */
6146       g_assert (i + 1 == stream->n_segments);
6147       break;
6148     }
6149   }
6150 }
6151
6152 static GstFlowReturn
6153 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6154 {
6155   GstQTDemux *demux;
6156
6157   demux = GST_QTDEMUX (parent);
6158
6159   GST_DEBUG_OBJECT (demux,
6160       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6161       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6162       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6163       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6164       gst_buffer_get_size (inbuf), demux->offset);
6165
6166   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6167     gboolean is_gap_input = FALSE;
6168     gint i;
6169
6170     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6171
6172     for (i = 0; i < demux->n_streams; i++) {
6173       demux->streams[i]->discont = TRUE;
6174     }
6175
6176     /* Check if we can land back on our feet in the case where upstream is
6177      * handling the seeking/pushing of samples with gaps in between (like
6178      * in the case of trick-mode DASH for example) */
6179     if (demux->upstream_format_is_time
6180         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6181       gint i;
6182       for (i = 0; i < demux->n_streams; i++) {
6183         guint32 res;
6184         GST_LOG_OBJECT (demux,
6185             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6186             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6187         res =
6188             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6189             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6190         if (res != -1) {
6191           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6192           GST_LOG_OBJECT (demux,
6193               "Checking if sample %d from stream %d is valid (offset:%"
6194               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6195               sample->offset, sample->size);
6196           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6197             GST_LOG_OBJECT (demux,
6198                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6199                 res);
6200             is_gap_input = TRUE;
6201             /* We can go back to standard playback mode */
6202             demux->state = QTDEMUX_STATE_MOVIE;
6203             /* Remember which sample this stream is at */
6204             demux->streams[i]->sample_index = res;
6205             /* Finally update all push-based values to the expected values */
6206             demux->neededbytes = demux->streams[i]->samples[res].size;
6207             demux->todrop = 0;
6208             demux->offset = GST_BUFFER_OFFSET (inbuf);
6209           }
6210         }
6211       }
6212       if (!is_gap_input) {
6213         /* Reset state if it's a real discont */
6214         demux->neededbytes = 16;
6215         demux->state = QTDEMUX_STATE_INITIAL;
6216         demux->offset = GST_BUFFER_OFFSET (inbuf);
6217       }
6218     }
6219     /* Reverse fragmented playback, need to flush all we have before
6220      * consuming a new fragment.
6221      * The samples array have the timestamps calculated by accumulating the
6222      * durations but this won't work for reverse playback of fragments as
6223      * the timestamps of a subsequent fragment should be smaller than the
6224      * previously received one. */
6225     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6226       gst_qtdemux_process_adapter (demux, TRUE);
6227       for (i = 0; i < demux->n_streams; i++)
6228         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6229     }
6230   }
6231
6232   gst_adapter_push (demux->adapter, inbuf);
6233
6234   GST_DEBUG_OBJECT (demux,
6235       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6236       demux->neededbytes, gst_adapter_available (demux->adapter));
6237
6238   return gst_qtdemux_process_adapter (demux, FALSE);
6239 }
6240
6241 static GstFlowReturn
6242 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6243 {
6244   GstFlowReturn ret = GST_FLOW_OK;
6245
6246   /* we never really mean to buffer that much */
6247   if (demux->neededbytes == -1) {
6248     goto eos;
6249   }
6250
6251   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6252       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6253
6254 #ifndef GST_DISABLE_GST_DEBUG
6255     {
6256       guint64 discont_offset, distance_from_discont;
6257
6258       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6259       distance_from_discont =
6260           gst_adapter_distance_from_discont (demux->adapter);
6261
6262       GST_DEBUG_OBJECT (demux,
6263           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6264           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6265           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6266           demux->offset, discont_offset, distance_from_discont);
6267     }
6268 #endif
6269
6270     switch (demux->state) {
6271       case QTDEMUX_STATE_INITIAL:{
6272         const guint8 *data;
6273         guint32 fourcc;
6274         guint64 size;
6275
6276         gst_qtdemux_check_seekability (demux);
6277
6278         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6279
6280         /* get fourcc/length, set neededbytes */
6281         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6282             &size, &fourcc);
6283         gst_adapter_unmap (demux->adapter);
6284         data = NULL;
6285         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6286             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6287         if (size == 0) {
6288           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6289               (_("This file is invalid and cannot be played.")),
6290               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6291                   GST_FOURCC_ARGS (fourcc)));
6292           ret = GST_FLOW_ERROR;
6293           break;
6294         }
6295         if (fourcc == FOURCC_mdat) {
6296           gint next_entry = next_entry_size (demux);
6297           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6298             /* we have the headers, start playback */
6299             demux->state = QTDEMUX_STATE_MOVIE;
6300             demux->neededbytes = next_entry;
6301             demux->mdatleft = size;
6302           } else {
6303             /* no headers yet, try to get them */
6304             guint bs;
6305             gboolean res;
6306             guint64 old, target;
6307
6308           buffer_data:
6309             old = demux->offset;
6310             target = old + size;
6311
6312             /* try to jump over the atom with a seek */
6313             /* only bother if it seems worth doing so,
6314              * and avoids possible upstream/server problems */
6315             if (demux->upstream_seekable &&
6316                 demux->upstream_size > 4 * (1 << 20)) {
6317               res = qtdemux_seek_offset (demux, target);
6318             } else {
6319               GST_DEBUG_OBJECT (demux, "skipping seek");
6320               res = FALSE;
6321             }
6322
6323             if (res) {
6324               GST_DEBUG_OBJECT (demux, "seek success");
6325               /* remember the offset fo the first mdat so we can seek back to it
6326                * after we have the headers */
6327               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6328                 demux->first_mdat = old;
6329                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6330                     demux->first_mdat);
6331               }
6332               /* seek worked, continue reading */
6333               demux->offset = target;
6334               demux->neededbytes = 16;
6335               demux->state = QTDEMUX_STATE_INITIAL;
6336             } else {
6337               /* seek failed, need to buffer */
6338               demux->offset = old;
6339               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6340               /* there may be multiple mdat (or alike) buffers */
6341               /* sanity check */
6342               if (demux->mdatbuffer)
6343                 bs = gst_buffer_get_size (demux->mdatbuffer);
6344               else
6345                 bs = 0;
6346               if (size + bs > 10 * (1 << 20))
6347                 goto no_moov;
6348               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6349               demux->neededbytes = size;
6350               if (!demux->mdatbuffer)
6351                 demux->mdatoffset = demux->offset;
6352             }
6353           }
6354         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6355           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6356               (_("This file is invalid and cannot be played.")),
6357               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6358                   GST_FOURCC_ARGS (fourcc), size));
6359           ret = GST_FLOW_ERROR;
6360           break;
6361         } else {
6362           /* this means we already started buffering and still no moov header,
6363            * let's continue buffering everything till we get moov */
6364           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6365                   || fourcc == FOURCC_moof))
6366             goto buffer_data;
6367           demux->neededbytes = size;
6368           demux->state = QTDEMUX_STATE_HEADER;
6369         }
6370         break;
6371       }
6372       case QTDEMUX_STATE_HEADER:{
6373         const guint8 *data;
6374         guint32 fourcc;
6375
6376         GST_DEBUG_OBJECT (demux, "In header");
6377
6378         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6379
6380         /* parse the header */
6381         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6382             &fourcc);
6383         if (fourcc == FOURCC_moov) {
6384           gint n;
6385
6386           /* in usual fragmented setup we could try to scan for more
6387            * and end up at the the moov (after mdat) again */
6388           if (demux->got_moov && demux->n_streams > 0 &&
6389               (!demux->fragmented
6390                   || demux->last_moov_offset == demux->offset)) {
6391             GST_DEBUG_OBJECT (demux,
6392                 "Skipping moov atom as we have (this) one already");
6393           } else {
6394             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6395
6396             if (demux->got_moov && demux->fragmented) {
6397               GST_DEBUG_OBJECT (demux,
6398                   "Got a second moov, clean up data from old one");
6399               if (demux->moov_node_compressed) {
6400                 g_node_destroy (demux->moov_node_compressed);
6401                 if (demux->moov_node)
6402                   g_free (demux->moov_node->data);
6403               }
6404               demux->moov_node_compressed = NULL;
6405               if (demux->moov_node)
6406                 g_node_destroy (demux->moov_node);
6407               demux->moov_node = NULL;
6408             } else {
6409               /* prepare newsegment to send when streaming actually starts */
6410               if (!demux->pending_newsegment) {
6411                 demux->pending_newsegment =
6412                     gst_event_new_segment (&demux->segment);
6413                 if (demux->segment_seqnum)
6414                   gst_event_set_seqnum (demux->pending_newsegment,
6415                       demux->segment_seqnum);
6416               }
6417             }
6418
6419             demux->last_moov_offset = demux->offset;
6420
6421             qtdemux_parse_moov (demux, data, demux->neededbytes);
6422             qtdemux_node_dump (demux, demux->moov_node);
6423             qtdemux_parse_tree (demux);
6424             qtdemux_prepare_streams (demux);
6425             if (!demux->got_moov)
6426               qtdemux_expose_streams (demux);
6427             else {
6428
6429               for (n = 0; n < demux->n_streams; n++) {
6430                 QtDemuxStream *stream = demux->streams[n];
6431
6432                 gst_qtdemux_configure_stream (demux, stream);
6433               }
6434             }
6435
6436             demux->got_moov = TRUE;
6437             gst_qtdemux_check_send_pending_segment (demux);
6438
6439             /* fragmented streams headers shouldn't contain edts atoms */
6440             if (!demux->fragmented) {
6441               for (n = 0; n < demux->n_streams; n++) {
6442                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6443                     demux->streams[n]);
6444               }
6445             }
6446
6447             if (demux->moov_node_compressed) {
6448               g_node_destroy (demux->moov_node_compressed);
6449               g_free (demux->moov_node->data);
6450             }
6451             demux->moov_node_compressed = NULL;
6452             g_node_destroy (demux->moov_node);
6453             demux->moov_node = NULL;
6454             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6455           }
6456         } else if (fourcc == FOURCC_moof) {
6457           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6458             guint64 dist = 0;
6459             GstClockTime prev_pts;
6460             guint64 prev_offset;
6461             guint64 adapter_discont_offset, adapter_discont_dist;
6462
6463             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6464
6465             /*
6466              * The timestamp of the moof buffer is relevant as some scenarios
6467              * won't have the initial timestamp in the atoms. Whenever a new
6468              * buffer has started, we get that buffer's PTS and use it as a base
6469              * timestamp for the trun entries.
6470              *
6471              * To keep track of the current buffer timestamp and starting point
6472              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6473              * from the beggining of the buffer, with the distance and demux->offset
6474              * we know if it is still the same buffer or not.
6475              */
6476             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6477             prev_offset = demux->offset - dist;
6478             if (demux->fragment_start_offset == -1
6479                 || prev_offset > demux->fragment_start_offset) {
6480               demux->fragment_start_offset = prev_offset;
6481               demux->fragment_start = prev_pts;
6482               GST_DEBUG_OBJECT (demux,
6483                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6484                   GST_TIME_FORMAT, demux->fragment_start_offset,
6485                   GST_TIME_ARGS (demux->fragment_start));
6486             }
6487
6488             /* We can't use prev_offset() here because this would require
6489              * upstream to set consistent and correct offsets on all buffers
6490              * since the discont. Nothing ever did that in the past and we
6491              * would break backwards compatibility here then.
6492              * Instead take the offset we had at the last discont and count
6493              * the bytes from there. This works with old code as there would
6494              * be no discont between moov and moof, and also works with
6495              * adaptivedemux which correctly sets offset and will set the
6496              * DISCONT flag accordingly when needed.
6497              *
6498              * We also only do this for upstream TIME segments as otherwise
6499              * there are potential backwards compatibility problems with
6500              * seeking in PUSH mode and upstream providing inconsistent
6501              * timestamps. */
6502             adapter_discont_offset =
6503                 gst_adapter_offset_at_discont (demux->adapter);
6504             adapter_discont_dist =
6505                 gst_adapter_distance_from_discont (demux->adapter);
6506
6507             GST_DEBUG_OBJECT (demux,
6508                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6509                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6510                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6511
6512             if (demux->upstream_format_is_time) {
6513               demux->moof_offset = adapter_discont_offset;
6514               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6515                 demux->moof_offset += adapter_discont_dist;
6516               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6517                 demux->moof_offset = demux->offset;
6518             } else {
6519               demux->moof_offset = demux->offset;
6520             }
6521
6522             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6523                     demux->moof_offset, NULL)) {
6524               gst_adapter_unmap (demux->adapter);
6525               ret = GST_FLOW_ERROR;
6526               goto done;
6527             }
6528             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6529             if (demux->mss_mode && !demux->exposed) {
6530               if (!demux->pending_newsegment) {
6531                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6532                 demux->pending_newsegment =
6533                     gst_event_new_segment (&demux->segment);
6534                 if (demux->segment_seqnum)
6535                   gst_event_set_seqnum (demux->pending_newsegment,
6536                       demux->segment_seqnum);
6537               }
6538               qtdemux_expose_streams (demux);
6539             }
6540           } else {
6541             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6542           }
6543         } else if (fourcc == FOURCC_ftyp) {
6544           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6545           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6546         } else if (fourcc == FOURCC_uuid) {
6547           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6548           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6549         } else if (fourcc == FOURCC_sidx) {
6550           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6551           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6552         } else {
6553           switch (fourcc) {
6554             case FOURCC_styp:
6555               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6556                * FALLTHROUGH */
6557             case FOURCC_free:
6558               /* [free] is a padding atom */
6559               GST_DEBUG_OBJECT (demux,
6560                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6561                   GST_FOURCC_ARGS (fourcc));
6562               break;
6563             default:
6564               GST_WARNING_OBJECT (demux,
6565                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6566                   GST_FOURCC_ARGS (fourcc));
6567               /* Let's jump that one and go back to initial state */
6568               break;
6569           }
6570         }
6571         gst_adapter_unmap (demux->adapter);
6572         data = NULL;
6573
6574         if (demux->mdatbuffer && demux->n_streams) {
6575           gsize remaining_data_size = 0;
6576
6577           /* the mdat was before the header */
6578           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6579               demux->n_streams, demux->mdatbuffer);
6580           /* restore our adapter/offset view of things with upstream;
6581            * put preceding buffered data ahead of current moov data.
6582            * This should also handle evil mdat, moov, mdat cases and alike */
6583           gst_adapter_flush (demux->adapter, demux->neededbytes);
6584
6585           /* Store any remaining data after the mdat for later usage */
6586           remaining_data_size = gst_adapter_available (demux->adapter);
6587           if (remaining_data_size > 0) {
6588             g_assert (demux->restoredata_buffer == NULL);
6589             demux->restoredata_buffer =
6590                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6591             demux->restoredata_offset = demux->offset + demux->neededbytes;
6592             GST_DEBUG_OBJECT (demux,
6593                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6594                 G_GUINT64_FORMAT, remaining_data_size,
6595                 demux->restoredata_offset);
6596           }
6597
6598           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6599           demux->mdatbuffer = NULL;
6600           demux->offset = demux->mdatoffset;
6601           demux->neededbytes = next_entry_size (demux);
6602           demux->state = QTDEMUX_STATE_MOVIE;
6603           demux->mdatleft = gst_adapter_available (demux->adapter);
6604         } else {
6605           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6606           gst_adapter_flush (demux->adapter, demux->neededbytes);
6607
6608           /* only go back to the mdat if there are samples to play */
6609           if (demux->got_moov && demux->first_mdat != -1
6610               && has_next_entry (demux)) {
6611             gboolean res;
6612
6613             /* we need to seek back */
6614             res = qtdemux_seek_offset (demux, demux->first_mdat);
6615             if (res) {
6616               demux->offset = demux->first_mdat;
6617             } else {
6618               GST_DEBUG_OBJECT (demux, "Seek back failed");
6619             }
6620           } else {
6621             demux->offset += demux->neededbytes;
6622           }
6623           demux->neededbytes = 16;
6624           demux->state = QTDEMUX_STATE_INITIAL;
6625         }
6626
6627         break;
6628       }
6629       case QTDEMUX_STATE_BUFFER_MDAT:{
6630         GstBuffer *buf;
6631         guint8 fourcc[4];
6632
6633         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6634             demux->offset);
6635         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6636         gst_buffer_extract (buf, 0, fourcc, 4);
6637         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6638             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6639         if (demux->mdatbuffer)
6640           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6641         else
6642           demux->mdatbuffer = buf;
6643         demux->offset += demux->neededbytes;
6644         demux->neededbytes = 16;
6645         demux->state = QTDEMUX_STATE_INITIAL;
6646         gst_qtdemux_post_progress (demux, 1, 1);
6647
6648         break;
6649       }
6650       case QTDEMUX_STATE_MOVIE:{
6651         QtDemuxStream *stream = NULL;
6652         QtDemuxSample *sample;
6653         int i = -1;
6654         GstClockTime dts, pts, duration;
6655         gboolean keyframe;
6656
6657         GST_DEBUG_OBJECT (demux,
6658             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6659
6660         if (demux->fragmented) {
6661           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6662               demux->mdatleft);
6663           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6664             /* if needed data starts within this atom,
6665              * then it should not exceed this atom */
6666             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6667               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6668                   (_("This file is invalid and cannot be played.")),
6669                   ("sample data crosses atom boundary"));
6670               ret = GST_FLOW_ERROR;
6671               break;
6672             }
6673             demux->mdatleft -= demux->neededbytes;
6674           } else {
6675             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6676             /* so we are dropping more than left in this atom */
6677             gst_qtdemux_drop_data (demux, demux->mdatleft);
6678             demux->mdatleft = 0;
6679
6680             /* need to resume atom parsing so we do not miss any other pieces */
6681             demux->state = QTDEMUX_STATE_INITIAL;
6682             demux->neededbytes = 16;
6683
6684             /* check if there was any stored post mdat data from previous buffers */
6685             if (demux->restoredata_buffer) {
6686               g_assert (gst_adapter_available (demux->adapter) == 0);
6687
6688               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6689               demux->restoredata_buffer = NULL;
6690               demux->offset = demux->restoredata_offset;
6691             }
6692
6693             break;
6694           }
6695         }
6696
6697         if (demux->todrop) {
6698           if (demux->cenc_aux_info_offset > 0) {
6699             GstByteReader br;
6700             const guint8 *data;
6701
6702             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6703             data = gst_adapter_map (demux->adapter, demux->todrop);
6704             gst_byte_reader_init (&br, data + 8, demux->todrop);
6705             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6706                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6707               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6708               ret = GST_FLOW_ERROR;
6709               gst_adapter_unmap (demux->adapter);
6710               g_free (demux->cenc_aux_info_sizes);
6711               demux->cenc_aux_info_sizes = NULL;
6712               goto done;
6713             }
6714             demux->cenc_aux_info_offset = 0;
6715             g_free (demux->cenc_aux_info_sizes);
6716             demux->cenc_aux_info_sizes = NULL;
6717             gst_adapter_unmap (demux->adapter);
6718           }
6719           gst_qtdemux_drop_data (demux, demux->todrop);
6720         }
6721
6722         /* first buffer? */
6723         /* initial newsegment sent here after having added pads,
6724          * possible others in sink_event */
6725         gst_qtdemux_check_send_pending_segment (demux);
6726
6727         /* Figure out which stream this packet belongs to */
6728         for (i = 0; i < demux->n_streams; i++) {
6729           stream = demux->streams[i];
6730           if (stream->sample_index >= stream->n_samples)
6731             continue;
6732           GST_LOG_OBJECT (demux,
6733               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6734               " / size:%d)", i, stream->sample_index,
6735               stream->samples[stream->sample_index].offset,
6736               stream->samples[stream->sample_index].size);
6737
6738           if (stream->samples[stream->sample_index].offset == demux->offset)
6739             break;
6740         }
6741
6742         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6743           goto unknown_stream;
6744
6745         if (stream->new_caps) {
6746           gst_qtdemux_configure_stream (demux, stream);
6747         }
6748
6749         /* Put data in a buffer, set timestamps, caps, ... */
6750         sample = &stream->samples[stream->sample_index];
6751
6752         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6753           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6754               GST_FOURCC_ARGS (stream->fourcc));
6755
6756           dts = QTSAMPLE_DTS (stream, sample);
6757           pts = QTSAMPLE_PTS (stream, sample);
6758           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6759           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6760
6761           /* check for segment end */
6762           if (G_UNLIKELY (demux->segment.stop != -1
6763                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6764             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6765             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6766
6767             /* skip this data, stream is EOS */
6768             gst_adapter_flush (demux->adapter, demux->neededbytes);
6769
6770             /* check if all streams are eos */
6771             ret = GST_FLOW_EOS;
6772             for (i = 0; i < demux->n_streams; i++) {
6773               if (!STREAM_IS_EOS (demux->streams[i])) {
6774                 ret = GST_FLOW_OK;
6775                 break;
6776               }
6777             }
6778
6779             if (ret == GST_FLOW_EOS) {
6780               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6781               goto eos;
6782             }
6783           } else {
6784             GstBuffer *outbuf;
6785
6786             outbuf =
6787                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6788
6789             /* FIXME: should either be an assert or a plain check */
6790             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6791
6792             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6793                 dts, pts, duration, keyframe, dts, demux->offset);
6794           }
6795
6796           /* combine flows */
6797           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6798           if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6799             goto non_ok_unlinked_flow;
6800         } else {
6801           /* skip this data, stream is EOS */
6802           gst_adapter_flush (demux->adapter, demux->neededbytes);
6803         }
6804
6805         stream->sample_index++;
6806         stream->offset_in_sample = 0;
6807
6808         /* update current offset and figure out size of next buffer */
6809         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6810             demux->offset, demux->neededbytes);
6811         demux->offset += demux->neededbytes;
6812         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6813             demux->offset);
6814
6815         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6816           if (demux->fragmented) {
6817             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6818             /* there may be more to follow, only finish this atom */
6819             demux->todrop = demux->mdatleft;
6820             demux->neededbytes = demux->todrop;
6821             break;
6822           }
6823           goto eos;
6824         }
6825         break;
6826       }
6827       default:
6828         goto invalid_state;
6829     }
6830   }
6831
6832   /* when buffering movie data, at least show user something is happening */
6833   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6834       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6835     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6836         demux->neededbytes);
6837   }
6838 done:
6839
6840   return ret;
6841
6842   /* ERRORS */
6843 non_ok_unlinked_flow:
6844   {
6845     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6846         gst_flow_get_name (ret));
6847     return ret;
6848   }
6849 unknown_stream:
6850   {
6851     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6852     ret = GST_FLOW_ERROR;
6853     goto done;
6854   }
6855 eos:
6856   {
6857     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6858     ret = GST_FLOW_EOS;
6859     goto done;
6860   }
6861 invalid_state:
6862   {
6863     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6864         (NULL), ("qtdemuxer invalid state %d", demux->state));
6865     ret = GST_FLOW_ERROR;
6866     goto done;
6867   }
6868 no_moov:
6869   {
6870     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6871         (NULL), ("no 'moov' atom within the first 10 MB"));
6872     ret = GST_FLOW_ERROR;
6873     goto done;
6874   }
6875 }
6876
6877 static gboolean
6878 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6879 {
6880   GstQuery *query;
6881   gboolean pull_mode;
6882
6883   query = gst_query_new_scheduling ();
6884
6885   if (!gst_pad_peer_query (sinkpad, query)) {
6886     gst_query_unref (query);
6887     goto activate_push;
6888   }
6889
6890   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6891       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6892   gst_query_unref (query);
6893
6894   if (!pull_mode)
6895     goto activate_push;
6896
6897   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6898   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6899
6900 activate_push:
6901   {
6902     GST_DEBUG_OBJECT (sinkpad, "activating push");
6903     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6904   }
6905 }
6906
6907 static gboolean
6908 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6909     GstPadMode mode, gboolean active)
6910 {
6911   gboolean res;
6912   GstQTDemux *demux = GST_QTDEMUX (parent);
6913
6914   switch (mode) {
6915     case GST_PAD_MODE_PUSH:
6916       demux->pullbased = FALSE;
6917       res = TRUE;
6918       break;
6919     case GST_PAD_MODE_PULL:
6920       if (active) {
6921         demux->pullbased = TRUE;
6922         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6923             sinkpad, NULL);
6924       } else {
6925         res = gst_pad_stop_task (sinkpad);
6926       }
6927       break;
6928     default:
6929       res = FALSE;
6930       break;
6931   }
6932   return res;
6933 }
6934
6935 #ifdef HAVE_ZLIB
6936 static void *
6937 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
6938 {
6939   guint8 *buffer;
6940   z_stream z;
6941   int ret;
6942
6943   memset (&z, 0, sizeof (z));
6944   z.zalloc = NULL;
6945   z.zfree = NULL;
6946   z.opaque = NULL;
6947
6948   if ((ret = inflateInit (&z)) != Z_OK) {
6949     GST_ERROR ("inflateInit() returned %d", ret);
6950     return NULL;
6951   }
6952
6953   z.next_in = z_buffer;
6954   z.avail_in = z_length;
6955
6956   buffer = (guint8 *) g_malloc (*length);
6957   z.avail_out = *length;
6958   z.next_out = (Bytef *) buffer;
6959   do {
6960     ret = inflate (&z, Z_NO_FLUSH);
6961     if (ret == Z_STREAM_END) {
6962       break;
6963     } else if (ret != Z_OK) {
6964       GST_WARNING ("inflate() returned %d", ret);
6965       break;
6966     }
6967
6968     *length += 4096;
6969     buffer = (guint8 *) g_realloc (buffer, *length);
6970     z.next_out = (Bytef *) (buffer + z.total_out);
6971     z.avail_out += 4096;
6972   } while (z.avail_in > 0);
6973
6974   if (ret != Z_STREAM_END) {
6975     g_free (buffer);
6976     buffer = NULL;
6977     *length = 0;
6978   } else {
6979     *length = z.total_out;
6980   }
6981
6982   inflateEnd (&z);
6983
6984   return buffer;
6985 }
6986 #endif /* HAVE_ZLIB */
6987
6988 static gboolean
6989 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6990 {
6991   GNode *cmov;
6992
6993   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6994
6995   /* counts as header data */
6996   qtdemux->header_size += length;
6997
6998   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6999   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7000
7001   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7002   if (cmov) {
7003     guint32 method;
7004     GNode *dcom;
7005     GNode *cmvd;
7006     guint32 dcom_len;
7007
7008     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7009     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7010     if (dcom == NULL || cmvd == NULL)
7011       goto invalid_compression;
7012
7013     dcom_len = QT_UINT32 (dcom->data);
7014     if (dcom_len < 12)
7015       goto invalid_compression;
7016
7017     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7018     switch (method) {
7019 #ifdef HAVE_ZLIB
7020       case FOURCC_zlib:{
7021         guint uncompressed_length;
7022         guint compressed_length;
7023         guint8 *buf;
7024         guint32 cmvd_len;
7025
7026         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7027         if (cmvd_len < 12)
7028           goto invalid_compression;
7029
7030         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7031         compressed_length = cmvd_len - 12;
7032         GST_LOG ("length = %u", uncompressed_length);
7033
7034         buf =
7035             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7036             compressed_length, &uncompressed_length);
7037
7038         if (buf) {
7039           qtdemux->moov_node_compressed = qtdemux->moov_node;
7040           qtdemux->moov_node = g_node_new (buf);
7041
7042           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7043               uncompressed_length);
7044         }
7045         break;
7046       }
7047 #endif /* HAVE_ZLIB */
7048       default:
7049         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7050             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7051         break;
7052     }
7053   }
7054   return TRUE;
7055
7056   /* ERRORS */
7057 invalid_compression:
7058   {
7059     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7060     return FALSE;
7061   }
7062 }
7063
7064 static gboolean
7065 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7066     const guint8 * end)
7067 {
7068   while (G_UNLIKELY (buf < end)) {
7069     GNode *child;
7070     guint32 len;
7071
7072     if (G_UNLIKELY (buf + 4 > end)) {
7073       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7074       break;
7075     }
7076     len = QT_UINT32 (buf);
7077     if (G_UNLIKELY (len == 0)) {
7078       GST_LOG_OBJECT (qtdemux, "empty container");
7079       break;
7080     }
7081     if (G_UNLIKELY (len < 8)) {
7082       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7083       break;
7084     }
7085     if (G_UNLIKELY (len > (end - buf))) {
7086       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7087           (gint) (end - buf));
7088       break;
7089     }
7090
7091     child = g_node_new ((guint8 *) buf);
7092     g_node_append (node, child);
7093     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7094     qtdemux_parse_node (qtdemux, child, buf, len);
7095
7096     buf += len;
7097   }
7098   return TRUE;
7099 }
7100
7101 static gboolean
7102 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7103     GNode * xdxt)
7104 {
7105   int len = QT_UINT32 (xdxt->data);
7106   guint8 *buf = xdxt->data;
7107   guint8 *end = buf + len;
7108   GstBuffer *buffer;
7109
7110   /* skip size and type */
7111   buf += 8;
7112   end -= 8;
7113
7114   while (buf < end) {
7115     gint size;
7116     guint32 type;
7117
7118     size = QT_UINT32 (buf);
7119     type = QT_FOURCC (buf + 4);
7120
7121     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7122
7123     if (buf + size > end || size <= 0)
7124       break;
7125
7126     buf += 8;
7127     size -= 8;
7128
7129     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7130         GST_FOURCC_ARGS (type));
7131
7132     switch (type) {
7133       case FOURCC_tCtH:
7134         buffer = gst_buffer_new_and_alloc (size);
7135         gst_buffer_fill (buffer, 0, buf, size);
7136         stream->buffers = g_slist_append (stream->buffers, buffer);
7137         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7138         break;
7139       case FOURCC_tCt_:
7140         buffer = gst_buffer_new_and_alloc (size);
7141         gst_buffer_fill (buffer, 0, buf, size);
7142         stream->buffers = g_slist_append (stream->buffers, buffer);
7143         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7144         break;
7145       case FOURCC_tCtC:
7146         buffer = gst_buffer_new_and_alloc (size);
7147         gst_buffer_fill (buffer, 0, buf, size);
7148         stream->buffers = g_slist_append (stream->buffers, buffer);
7149         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7150         break;
7151       default:
7152         GST_WARNING_OBJECT (qtdemux,
7153             "unknown theora cookie %" GST_FOURCC_FORMAT,
7154             GST_FOURCC_ARGS (type));
7155         break;
7156     }
7157     buf += size;
7158   }
7159   return TRUE;
7160 }
7161
7162 static gboolean
7163 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7164     guint length)
7165 {
7166   guint32 fourcc = 0;
7167   guint32 node_length = 0;
7168   const QtNodeType *type;
7169   const guint8 *end;
7170
7171   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7172
7173   if (G_UNLIKELY (length < 8))
7174     goto not_enough_data;
7175
7176   node_length = QT_UINT32 (buffer);
7177   fourcc = QT_FOURCC (buffer + 4);
7178
7179   /* ignore empty nodes */
7180   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7181     return TRUE;
7182
7183   type = qtdemux_type_get (fourcc);
7184
7185   end = buffer + length;
7186
7187   GST_LOG_OBJECT (qtdemux,
7188       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7189       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7190
7191   if (node_length > length)
7192     goto broken_atom_size;
7193
7194   if (type->flags & QT_FLAG_CONTAINER) {
7195     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7196   } else {
7197     switch (fourcc) {
7198       case FOURCC_stsd:
7199       {
7200         if (node_length < 20) {
7201           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7202           break;
7203         }
7204         GST_DEBUG_OBJECT (qtdemux,
7205             "parsing stsd (sample table, sample description) atom");
7206         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7207         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7208         break;
7209       }
7210       case FOURCC_mp4a:
7211       case FOURCC_alac:
7212       case FOURCC_fLaC:
7213       {
7214         guint32 version;
7215         guint32 offset;
7216         guint min_size;
7217
7218         /* also read alac (or whatever) in stead of mp4a in the following,
7219          * since a similar layout is used in other cases as well */
7220         if (fourcc == FOURCC_mp4a)
7221           min_size = 20;
7222         else if (fourcc == FOURCC_fLaC)
7223           min_size = 86;
7224         else
7225           min_size = 40;
7226
7227         /* There are two things we might encounter here: a true mp4a atom, and
7228            an mp4a entry in an stsd atom. The latter is what we're interested
7229            in, and it looks like an atom, but isn't really one. The true mp4a
7230            atom is short, so we detect it based on length here. */
7231         if (length < min_size) {
7232           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7233               GST_FOURCC_ARGS (fourcc));
7234           break;
7235         }
7236
7237         /* 'version' here is the sound sample description version. Types 0 and
7238            1 are documented in the QTFF reference, but type 2 is not: it's
7239            described in Apple header files instead (struct SoundDescriptionV2
7240            in Movies.h) */
7241         version = QT_UINT16 (buffer + 16);
7242
7243         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7244             GST_FOURCC_ARGS (fourcc), version);
7245
7246         /* parse any esds descriptors */
7247         switch (version) {
7248           case 0:
7249             offset = 0x24;
7250             break;
7251           case 1:
7252             offset = 0x34;
7253             break;
7254           case 2:
7255             offset = 0x48;
7256             break;
7257           default:
7258             GST_WARNING_OBJECT (qtdemux,
7259                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7260                 GST_FOURCC_ARGS (fourcc), version);
7261             offset = 0;
7262             break;
7263         }
7264         if (offset)
7265           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7266         break;
7267       }
7268       case FOURCC_mp4v:
7269       case FOURCC_MP4V:
7270       case FOURCC_fmp4:
7271       case FOURCC_FMP4:
7272       case FOURCC_apcs:
7273       case FOURCC_apch:
7274       case FOURCC_apcn:
7275       case FOURCC_apco:
7276       case FOURCC_ap4h:
7277       case FOURCC_xvid:
7278       case FOURCC_XVID:
7279       case FOURCC_H264:
7280       case FOURCC_avc1:
7281       case FOURCC_avc3:
7282       case FOURCC_H265:
7283       case FOURCC_hvc1:
7284       case FOURCC_hev1:
7285       case FOURCC_mjp2:
7286       case FOURCC_encv:
7287       {
7288         guint32 version;
7289         guint32 str_len;
7290
7291         /* codec_data is contained inside these atoms, which all have
7292          * the same format. */
7293         /* video sample description size is 86 bytes without extension.
7294          * node_length have to be bigger than 86 bytes because video sample
7295          * description can include extenstions such as esds, fiel, glbl, etc. */
7296         if (node_length < 86) {
7297           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7298               " sample description length too short (%u < 86)",
7299               GST_FOURCC_ARGS (fourcc), node_length);
7300           break;
7301         }
7302
7303         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7304             GST_FOURCC_ARGS (fourcc));
7305
7306         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7307          *              its data format.
7308          * revision level (2 bytes) : must be set to 0. */
7309         version = QT_UINT32 (buffer + 16);
7310         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7311
7312         /* compressor name : PASCAL string and informative purposes
7313          * first byte : the number of bytes to be displayed.
7314          *              it has to be less than 32 because it is reserved
7315          *              space of 32 bytes total including itself. */
7316         str_len = QT_UINT8 (buffer + 50);
7317         if (str_len < 32)
7318           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7319               (char *) buffer + 51);
7320         else
7321           GST_WARNING_OBJECT (qtdemux,
7322               "compressorname length too big (%u > 31)", str_len);
7323
7324         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7325             end - buffer);
7326         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7327         break;
7328       }
7329       case FOURCC_meta:
7330       {
7331         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7332         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7333         break;
7334       }
7335       case FOURCC_mp4s:
7336       {
7337         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7338         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7339         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7340         break;
7341       }
7342       case FOURCC_XiTh:
7343       {
7344         guint32 version;
7345         guint32 offset;
7346
7347         if (length < 16) {
7348           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7349               GST_FOURCC_ARGS (fourcc));
7350           break;
7351         }
7352
7353         version = QT_UINT32 (buffer + 12);
7354         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7355
7356         switch (version) {
7357           case 0x00000001:
7358             offset = 0x62;
7359             break;
7360           default:
7361             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7362             offset = 0;
7363             break;
7364         }
7365         if (offset) {
7366           if (length < offset) {
7367             GST_WARNING_OBJECT (qtdemux,
7368                 "skipping too small %" GST_FOURCC_FORMAT " box",
7369                 GST_FOURCC_ARGS (fourcc));
7370             break;
7371           }
7372           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7373         }
7374         break;
7375       }
7376       case FOURCC_in24:
7377       {
7378         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7379         break;
7380       }
7381       case FOURCC_uuid:
7382       {
7383         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7384         break;
7385       }
7386       case FOURCC_enca:
7387       {
7388         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7389         break;
7390       }
7391       default:
7392         if (!strcmp (type->name, "unknown"))
7393           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7394         break;
7395     }
7396   }
7397   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7398       GST_FOURCC_ARGS (fourcc));
7399   return TRUE;
7400
7401 /* ERRORS */
7402 not_enough_data:
7403   {
7404     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7405         (_("This file is corrupt and cannot be played.")),
7406         ("Not enough data for an atom header, got only %u bytes", length));
7407     return FALSE;
7408   }
7409 broken_atom_size:
7410   {
7411     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7412         (_("This file is corrupt and cannot be played.")),
7413         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7414             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7415             length));
7416     return FALSE;
7417   }
7418 }
7419
7420 static GNode *
7421 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7422 {
7423   GNode *child;
7424   guint8 *buffer;
7425   guint32 child_fourcc;
7426
7427   for (child = g_node_first_child (node); child;
7428       child = g_node_next_sibling (child)) {
7429     buffer = (guint8 *) child->data;
7430
7431     child_fourcc = QT_FOURCC (buffer + 4);
7432
7433     if (G_UNLIKELY (child_fourcc == fourcc)) {
7434       return child;
7435     }
7436   }
7437   return NULL;
7438 }
7439
7440 static GNode *
7441 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7442     GstByteReader * parser)
7443 {
7444   GNode *child;
7445   guint8 *buffer;
7446   guint32 child_fourcc, child_len;
7447
7448   for (child = g_node_first_child (node); child;
7449       child = g_node_next_sibling (child)) {
7450     buffer = (guint8 *) child->data;
7451
7452     child_len = QT_UINT32 (buffer);
7453     child_fourcc = QT_FOURCC (buffer + 4);
7454
7455     if (G_UNLIKELY (child_fourcc == fourcc)) {
7456       if (G_UNLIKELY (child_len < (4 + 4)))
7457         return NULL;
7458       /* FIXME: must verify if atom length < parent atom length */
7459       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7460       return child;
7461     }
7462   }
7463   return NULL;
7464 }
7465
7466 static GNode *
7467 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7468     GstByteReader * parser)
7469 {
7470   GNode *child;
7471   guint8 *buffer;
7472   guint32 child_fourcc, child_len;
7473
7474   for (child = g_node_next_sibling (node); child;
7475       child = g_node_next_sibling (child)) {
7476     buffer = (guint8 *) child->data;
7477
7478     child_fourcc = QT_FOURCC (buffer + 4);
7479
7480     if (child_fourcc == fourcc) {
7481       if (parser) {
7482         child_len = QT_UINT32 (buffer);
7483         if (G_UNLIKELY (child_len < (4 + 4)))
7484           return NULL;
7485         /* FIXME: must verify if atom length < parent atom length */
7486         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7487       }
7488       return child;
7489     }
7490   }
7491   return NULL;
7492 }
7493
7494 static GNode *
7495 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7496 {
7497   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7498 }
7499
7500 static void
7501 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7502 {
7503 /* FIXME: This can only reliably work if demuxers have a
7504  * separate streaming thread per srcpad. This should be
7505  * done in a demuxer base class, which integrates parts
7506  * of multiqueue
7507  *
7508  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7509  */
7510 #if 0
7511   GstQuery *query;
7512
7513   query = gst_query_new_allocation (stream->caps, FALSE);
7514
7515   if (!gst_pad_peer_query (stream->pad, query)) {
7516     /* not a problem, just debug a little */
7517     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7518   }
7519
7520   if (stream->allocator)
7521     gst_object_unref (stream->allocator);
7522
7523   if (gst_query_get_n_allocation_params (query) > 0) {
7524     /* try the allocator */
7525     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7526         &stream->params);
7527     stream->use_allocator = TRUE;
7528   } else {
7529     stream->allocator = NULL;
7530     gst_allocation_params_init (&stream->params);
7531     stream->use_allocator = FALSE;
7532   }
7533   gst_query_unref (query);
7534 #endif
7535 }
7536
7537 static gboolean
7538 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7539     QtDemuxStream * stream)
7540 {
7541   GstStructure *s;
7542   const gchar *selected_system;
7543
7544   g_return_val_if_fail (qtdemux != NULL, FALSE);
7545   g_return_val_if_fail (stream != NULL, FALSE);
7546   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
7547
7548   if (stream->protection_scheme_type != FOURCC_cenc) {
7549     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7550     return FALSE;
7551   }
7552   if (qtdemux->protection_system_ids == NULL) {
7553     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7554         "cenc protection system information has been found");
7555     return FALSE;
7556   }
7557   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7558   selected_system = gst_protection_select_system ((const gchar **)
7559       qtdemux->protection_system_ids->pdata);
7560   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7561       qtdemux->protection_system_ids->len - 1);
7562   if (!selected_system) {
7563     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7564         "suitable decryptor element has been found");
7565     return FALSE;
7566   }
7567
7568   s = gst_caps_get_structure (stream->caps, 0);
7569   if (!gst_structure_has_name (s, "application/x-cenc")) {
7570     gst_structure_set (s,
7571         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7572         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7573         NULL);
7574     gst_structure_set_name (s, "application/x-cenc");
7575   }
7576   return TRUE;
7577 }
7578
7579 static gboolean
7580 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7581 {
7582   if (stream->subtype == FOURCC_vide) {
7583     /* fps is calculated base on the duration of the average framerate since
7584      * qt does not have a fixed framerate. */
7585     gboolean fps_available = TRUE;
7586
7587     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7588       /* still frame */
7589       stream->fps_n = 0;
7590       stream->fps_d = 1;
7591     } else {
7592       if (stream->duration == 0 || stream->n_samples < 2) {
7593         stream->fps_n = stream->timescale;
7594         stream->fps_d = 1;
7595         fps_available = FALSE;
7596       } else {
7597         GstClockTime avg_duration;
7598         guint64 duration;
7599         guint32 n_samples;
7600
7601         /* duration and n_samples can be updated for fragmented format
7602          * so, framerate of fragmented format is calculated using data in a moof */
7603         if (qtdemux->fragmented && stream->n_samples_moof > 0
7604             && stream->duration_moof > 0) {
7605           n_samples = stream->n_samples_moof;
7606           duration = stream->duration_moof;
7607         } else {
7608           n_samples = stream->n_samples;
7609           duration = stream->duration;
7610         }
7611
7612         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7613         /* stream->duration is guint64, timescale, n_samples are guint32 */
7614         avg_duration =
7615             gst_util_uint64_scale_round (duration -
7616             stream->first_duration, GST_SECOND,
7617             (guint64) (stream->timescale) * (n_samples - 1));
7618
7619         GST_LOG_OBJECT (qtdemux,
7620             "Calculating avg sample duration based on stream (or moof) duration %"
7621             G_GUINT64_FORMAT
7622             " minus first sample %u, leaving %d samples gives %"
7623             GST_TIME_FORMAT, duration, stream->first_duration,
7624             n_samples - 1, GST_TIME_ARGS (avg_duration));
7625
7626         gst_video_guess_framerate (avg_duration, &stream->fps_n,
7627             &stream->fps_d);
7628
7629         GST_DEBUG_OBJECT (qtdemux,
7630             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7631             stream->timescale, stream->fps_n, stream->fps_d);
7632       }
7633     }
7634
7635     if (stream->caps) {
7636       stream->caps = gst_caps_make_writable (stream->caps);
7637
7638       gst_caps_set_simple (stream->caps,
7639           "width", G_TYPE_INT, stream->width,
7640           "height", G_TYPE_INT, stream->height, NULL);
7641
7642       /* set framerate if calculated framerate is reliable */
7643       if (fps_available) {
7644         gst_caps_set_simple (stream->caps,
7645             "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
7646       }
7647
7648       /* calculate pixel-aspect-ratio using display width and height */
7649       GST_DEBUG_OBJECT (qtdemux,
7650           "video size %dx%d, target display size %dx%d", stream->width,
7651           stream->height, stream->display_width, stream->display_height);
7652       /* qt file might have pasp atom */
7653       if (stream->par_w > 0 && stream->par_h > 0) {
7654         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
7655         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7656             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7657       } else if (stream->display_width > 0 && stream->display_height > 0 &&
7658           stream->width > 0 && stream->height > 0) {
7659         gint n, d;
7660
7661         /* calculate the pixel aspect ratio using the display and pixel w/h */
7662         n = stream->display_width * stream->height;
7663         d = stream->display_height * stream->width;
7664         if (n == d)
7665           n = d = 1;
7666         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7667         stream->par_w = n;
7668         stream->par_h = d;
7669         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
7670             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
7671       }
7672
7673       if (stream->interlace_mode > 0) {
7674         if (stream->interlace_mode == 1) {
7675           gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
7676               "progressive", NULL);
7677         } else if (stream->interlace_mode == 2) {
7678           gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_STRING,
7679               "interleaved", NULL);
7680           if (stream->field_order == 9) {
7681             gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
7682                 "top-field-first", NULL);
7683           } else if (stream->field_order == 14) {
7684             gst_caps_set_simple (stream->caps, "field-order", G_TYPE_STRING,
7685                 "bottom-field-first", NULL);
7686           }
7687         }
7688       }
7689
7690       /* Create incomplete colorimetry here if needed */
7691       if (stream->colorimetry.range ||
7692           stream->colorimetry.matrix ||
7693           stream->colorimetry.transfer || stream->colorimetry.primaries) {
7694         gchar *colorimetry =
7695             gst_video_colorimetry_to_string (&stream->colorimetry);
7696         gst_caps_set_simple (stream->caps, "colorimetry", G_TYPE_STRING,
7697             colorimetry, NULL);
7698         g_free (colorimetry);
7699       }
7700
7701       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7702         guint par_w = 1, par_h = 1;
7703
7704         if (stream->par_w > 0 && stream->par_h > 0) {
7705           par_w = stream->par_w;
7706           par_h = stream->par_h;
7707         }
7708
7709         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7710                 stream->width, stream->height, par_w, par_h)) {
7711           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7712         }
7713
7714         gst_caps_set_simple (stream->caps,
7715             "multiview-mode", G_TYPE_STRING,
7716             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7717             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7718             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7719       }
7720     }
7721   }
7722
7723   else if (stream->subtype == FOURCC_soun) {
7724     if (stream->caps) {
7725       stream->caps = gst_caps_make_writable (stream->caps);
7726       if (stream->rate > 0)
7727         gst_caps_set_simple (stream->caps,
7728             "rate", G_TYPE_INT, (int) stream->rate, NULL);
7729       if (stream->n_channels > 0)
7730         gst_caps_set_simple (stream->caps,
7731             "channels", G_TYPE_INT, stream->n_channels, NULL);
7732       if (stream->n_channels > 2) {
7733         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7734          * correctly; this is just the minimum we can do - assume
7735          * we don't actually have any channel positions. */
7736         gst_caps_set_simple (stream->caps,
7737             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7738       }
7739     }
7740   }
7741
7742   if (stream->pad) {
7743     GstCaps *prev_caps = NULL;
7744
7745     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7746     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7747     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7748     gst_pad_set_active (stream->pad, TRUE);
7749
7750     gst_pad_use_fixed_caps (stream->pad);
7751
7752     if (stream->protected) {
7753       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7754         GST_ERROR_OBJECT (qtdemux,
7755             "Failed to configure protected stream caps.");
7756         return FALSE;
7757       }
7758     }
7759
7760     if (stream->new_stream) {
7761       gchar *stream_id;
7762       GstEvent *event;
7763       GstStreamFlags stream_flags;
7764
7765       event =
7766           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7767           0);
7768       if (event) {
7769         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7770           qtdemux->have_group_id = TRUE;
7771         else
7772           qtdemux->have_group_id = FALSE;
7773         gst_event_unref (event);
7774       } else if (!qtdemux->have_group_id) {
7775         qtdemux->have_group_id = TRUE;
7776         qtdemux->group_id = gst_util_group_id_next ();
7777       }
7778
7779       stream->new_stream = FALSE;
7780       stream_id =
7781           gst_pad_create_stream_id_printf (stream->pad,
7782           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7783       event = gst_event_new_stream_start (stream_id);
7784       if (qtdemux->have_group_id)
7785         gst_event_set_group_id (event, qtdemux->group_id);
7786       stream_flags = GST_STREAM_FLAG_NONE;
7787       if (stream->disabled)
7788         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7789       if (stream->sparse)
7790         stream_flags |= GST_STREAM_FLAG_SPARSE;
7791       gst_event_set_stream_flags (event, stream_flags);
7792       gst_pad_push_event (stream->pad, event);
7793       g_free (stream_id);
7794     }
7795
7796     prev_caps = gst_pad_get_current_caps (stream->pad);
7797
7798     if (!prev_caps || !gst_caps_is_equal_fixed (prev_caps, stream->caps)) {
7799       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
7800       gst_pad_set_caps (stream->pad, stream->caps);
7801     } else {
7802       GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7803     }
7804
7805     if (prev_caps)
7806       gst_caps_unref (prev_caps);
7807     stream->new_caps = FALSE;
7808   }
7809   return TRUE;
7810 }
7811
7812 static gboolean
7813 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7814     QtDemuxStream * stream, GstTagList * list)
7815 {
7816   gboolean ret = TRUE;
7817   /* consistent default for push based mode */
7818   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7819
7820   if (stream->subtype == FOURCC_vide) {
7821     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7822
7823     stream->pad =
7824         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7825     g_free (name);
7826
7827     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7828       gst_object_unref (stream->pad);
7829       stream->pad = NULL;
7830       ret = FALSE;
7831       goto done;
7832     }
7833
7834     qtdemux->n_video_streams++;
7835   } else if (stream->subtype == FOURCC_soun) {
7836     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7837
7838     stream->pad =
7839         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7840     g_free (name);
7841     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7842       gst_object_unref (stream->pad);
7843       stream->pad = NULL;
7844       ret = FALSE;
7845       goto done;
7846     }
7847     qtdemux->n_audio_streams++;
7848   } else if (stream->subtype == FOURCC_strm) {
7849     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
7850   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
7851       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
7852     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
7853
7854     stream->pad =
7855         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
7856     g_free (name);
7857     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7858       gst_object_unref (stream->pad);
7859       stream->pad = NULL;
7860       ret = FALSE;
7861       goto done;
7862     }
7863     qtdemux->n_sub_streams++;
7864   } else if (stream->caps) {
7865     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7866
7867     stream->pad =
7868         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7869     g_free (name);
7870     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7871       gst_object_unref (stream->pad);
7872       stream->pad = NULL;
7873       ret = FALSE;
7874       goto done;
7875     }
7876     qtdemux->n_video_streams++;
7877   } else {
7878     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
7879     goto done;
7880   }
7881
7882   if (stream->pad) {
7883     GList *l;
7884
7885     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
7886         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
7887     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
7888     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
7889
7890     if (stream->pending_tags)
7891       gst_tag_list_unref (stream->pending_tags);
7892     stream->pending_tags = list;
7893     list = NULL;
7894     /* global tags go on each pad anyway */
7895     stream->send_global_tags = TRUE;
7896     /* send upstream GST_EVENT_PROTECTION events that were received before
7897        this source pad was created */
7898     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7899       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7900   }
7901 done:
7902   if (list)
7903     gst_tag_list_unref (list);
7904   return ret;
7905 }
7906
7907 /* find next atom with @fourcc starting at @offset */
7908 static GstFlowReturn
7909 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7910     guint64 * length, guint32 fourcc)
7911 {
7912   GstFlowReturn ret;
7913   guint32 lfourcc;
7914   GstBuffer *buf;
7915
7916   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7917       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7918
7919   while (TRUE) {
7920     GstMapInfo map;
7921
7922     buf = NULL;
7923     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7924     if (G_UNLIKELY (ret != GST_FLOW_OK))
7925       goto locate_failed;
7926     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7927       /* likely EOF */
7928       ret = GST_FLOW_EOS;
7929       gst_buffer_unref (buf);
7930       goto locate_failed;
7931     }
7932     gst_buffer_map (buf, &map, GST_MAP_READ);
7933     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7934     gst_buffer_unmap (buf, &map);
7935     gst_buffer_unref (buf);
7936
7937     if (G_UNLIKELY (*length == 0)) {
7938       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7939       ret = GST_FLOW_ERROR;
7940       goto locate_failed;
7941     }
7942
7943     if (lfourcc == fourcc) {
7944       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7945           *offset);
7946       break;
7947     } else {
7948       GST_LOG_OBJECT (qtdemux,
7949           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7950           GST_FOURCC_ARGS (fourcc), *offset);
7951       *offset += *length;
7952     }
7953   }
7954
7955   return GST_FLOW_OK;
7956
7957 locate_failed:
7958   {
7959     /* might simply have had last one */
7960     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7961     return ret;
7962   }
7963 }
7964
7965 /* should only do something in pull mode */
7966 /* call with OBJECT lock */
7967 static GstFlowReturn
7968 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7969 {
7970   guint64 length, offset;
7971   GstBuffer *buf = NULL;
7972   GstFlowReturn ret = GST_FLOW_OK;
7973   GstFlowReturn res = GST_FLOW_OK;
7974   GstMapInfo map;
7975
7976   offset = qtdemux->moof_offset;
7977   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7978
7979   if (!offset) {
7980     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7981     return GST_FLOW_EOS;
7982   }
7983
7984   /* best not do pull etc with lock held */
7985   GST_OBJECT_UNLOCK (qtdemux);
7986
7987   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7988   if (ret != GST_FLOW_OK)
7989     goto flow_failed;
7990
7991   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7992   if (G_UNLIKELY (ret != GST_FLOW_OK))
7993     goto flow_failed;
7994   gst_buffer_map (buf, &map, GST_MAP_READ);
7995   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7996     gst_buffer_unmap (buf, &map);
7997     gst_buffer_unref (buf);
7998     buf = NULL;
7999     goto parse_failed;
8000   }
8001
8002   gst_buffer_unmap (buf, &map);
8003   gst_buffer_unref (buf);
8004   buf = NULL;
8005
8006   offset += length;
8007   /* look for next moof */
8008   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8009   if (G_UNLIKELY (ret != GST_FLOW_OK))
8010     goto flow_failed;
8011
8012 exit:
8013   GST_OBJECT_LOCK (qtdemux);
8014
8015   qtdemux->moof_offset = offset;
8016
8017   return res;
8018
8019 parse_failed:
8020   {
8021     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8022     offset = 0;
8023     res = GST_FLOW_ERROR;
8024     goto exit;
8025   }
8026 flow_failed:
8027   {
8028     /* maybe upstream temporarily flushing */
8029     if (ret != GST_FLOW_FLUSHING) {
8030       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8031       offset = 0;
8032     } else {
8033       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8034       /* resume at current position next time */
8035     }
8036     res = ret;
8037     goto exit;
8038   }
8039 }
8040
8041 /* initialise bytereaders for stbl sub-atoms */
8042 static gboolean
8043 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8044 {
8045   stream->stbl_index = -1;      /* no samples have yet been parsed */
8046   stream->sample_index = -1;
8047
8048   /* time-to-sample atom */
8049   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8050     goto corrupt_file;
8051
8052   /* copy atom data into a new buffer for later use */
8053   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8054
8055   /* skip version + flags */
8056   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8057       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8058     goto corrupt_file;
8059   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8060
8061   /* make sure there's enough data */
8062   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8063     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8064     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8065         stream->n_sample_times);
8066     if (!stream->n_sample_times)
8067       goto corrupt_file;
8068   }
8069
8070   /* sync sample atom */
8071   stream->stps_present = FALSE;
8072   if ((stream->stss_present =
8073           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8074               &stream->stss) ? TRUE : FALSE) == TRUE) {
8075     /* copy atom data into a new buffer for later use */
8076     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8077
8078     /* skip version + flags */
8079     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8080         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8081       goto corrupt_file;
8082
8083     if (stream->n_sample_syncs) {
8084       /* make sure there's enough data */
8085       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8086         goto corrupt_file;
8087     }
8088
8089     /* partial sync sample atom */
8090     if ((stream->stps_present =
8091             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8092                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8093       /* copy atom data into a new buffer for later use */
8094       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8095
8096       /* skip version + flags */
8097       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8098           !gst_byte_reader_get_uint32_be (&stream->stps,
8099               &stream->n_sample_partial_syncs))
8100         goto corrupt_file;
8101
8102       /* if there are no entries, the stss table contains the real
8103        * sync samples */
8104       if (stream->n_sample_partial_syncs) {
8105         /* make sure there's enough data */
8106         if (!qt_atom_parser_has_chunks (&stream->stps,
8107                 stream->n_sample_partial_syncs, 4))
8108           goto corrupt_file;
8109       }
8110     }
8111   }
8112
8113   /* sample size */
8114   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8115     goto no_samples;
8116
8117   /* copy atom data into a new buffer for later use */
8118   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8119
8120   /* skip version + flags */
8121   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8122       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8123     goto corrupt_file;
8124
8125   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8126     goto corrupt_file;
8127
8128   if (!stream->n_samples)
8129     goto no_samples;
8130
8131   /* sample-to-chunk atom */
8132   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8133     goto corrupt_file;
8134
8135   /* copy atom data into a new buffer for later use */
8136   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8137
8138   /* skip version + flags */
8139   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8140       !gst_byte_reader_get_uint32_be (&stream->stsc,
8141           &stream->n_samples_per_chunk))
8142     goto corrupt_file;
8143
8144   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8145       stream->n_samples_per_chunk);
8146
8147   /* make sure there's enough data */
8148   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8149           12))
8150     goto corrupt_file;
8151
8152
8153   /* chunk offset */
8154   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8155     stream->co_size = sizeof (guint32);
8156   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8157           &stream->stco))
8158     stream->co_size = sizeof (guint64);
8159   else
8160     goto corrupt_file;
8161
8162   /* copy atom data into a new buffer for later use */
8163   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8164
8165   /* skip version + flags */
8166   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8167     goto corrupt_file;
8168
8169   /* chunks_are_samples == TRUE means treat chunks as samples */
8170   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
8171   if (stream->chunks_are_samples) {
8172     /* treat chunks as samples */
8173     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8174       goto corrupt_file;
8175   } else {
8176     /* skip number of entries */
8177     if (!gst_byte_reader_skip (&stream->stco, 4))
8178       goto corrupt_file;
8179
8180     /* make sure there are enough data in the stsz atom */
8181     if (!stream->sample_size) {
8182       /* different sizes for each sample */
8183       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8184         goto corrupt_file;
8185     }
8186   }
8187
8188   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8189       stream->n_samples, (guint) sizeof (QtDemuxSample),
8190       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8191
8192   if (stream->n_samples >=
8193       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8194     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8195         "be larger than %uMB (broken file?)", stream->n_samples,
8196         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8197     return FALSE;
8198   }
8199
8200   g_assert (stream->samples == NULL);
8201   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8202   if (!stream->samples) {
8203     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8204         stream->n_samples);
8205     return FALSE;
8206   }
8207
8208   /* composition time-to-sample */
8209   if ((stream->ctts_present =
8210           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8211               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8212     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8213
8214     /* copy atom data into a new buffer for later use */
8215     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8216
8217     /* skip version + flags */
8218     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8219         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8220             &stream->n_composition_times))
8221       goto corrupt_file;
8222
8223     /* make sure there's enough data */
8224     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8225             4 + 4))
8226       goto corrupt_file;
8227
8228     /* This is optional, if missing we iterate the ctts */
8229     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8230       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8231           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8232         g_free ((gpointer) cslg.data);
8233         goto corrupt_file;
8234       }
8235     } else {
8236       gint32 cslg_least = 0;
8237       guint num_entries, pos;
8238       gint i;
8239
8240       pos = gst_byte_reader_get_pos (&stream->ctts);
8241       num_entries = stream->n_composition_times;
8242
8243       stream->cslg_shift = 0;
8244
8245       for (i = 0; i < num_entries; i++) {
8246         gint32 offset;
8247
8248         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8249         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8250
8251         if (offset < cslg_least)
8252           cslg_least = offset;
8253       }
8254
8255       if (cslg_least < 0)
8256         stream->cslg_shift = ABS (cslg_least);
8257       else
8258         stream->cslg_shift = 0;
8259
8260       /* reset the reader so we can generate sample table */
8261       gst_byte_reader_set_pos (&stream->ctts, pos);
8262     }
8263   } else {
8264     /* Ensure the cslg_shift value is consistent so we can use it
8265      * unconditionnally to produce TS and Segment */
8266     stream->cslg_shift = 0;
8267   }
8268
8269   return TRUE;
8270
8271 corrupt_file:
8272   {
8273     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8274         (_("This file is corrupt and cannot be played.")), (NULL));
8275     return FALSE;
8276   }
8277 no_samples:
8278   {
8279     gst_qtdemux_stbl_free (stream);
8280     if (!qtdemux->fragmented) {
8281       /* not quite good */
8282       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8283       return FALSE;
8284     } else {
8285       /* may pick up samples elsewhere */
8286       return TRUE;
8287     }
8288   }
8289 }
8290
8291 /* collect samples from the next sample to be parsed up to sample @n for @stream
8292  * by reading the info from @stbl
8293  *
8294  * This code can be executed from both the streaming thread and the seeking
8295  * thread so it takes the object lock to protect itself
8296  */
8297 static gboolean
8298 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8299 {
8300   gint i, j, k;
8301   QtDemuxSample *samples, *first, *cur, *last;
8302   guint32 n_samples_per_chunk;
8303   guint32 n_samples;
8304
8305   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8306       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
8307       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8308
8309   n_samples = stream->n_samples;
8310
8311   if (n >= n_samples)
8312     goto out_of_samples;
8313
8314   GST_OBJECT_LOCK (qtdemux);
8315   if (n <= stream->stbl_index)
8316     goto already_parsed;
8317
8318   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8319
8320   if (!stream->stsz.data) {
8321     /* so we already parsed and passed all the moov samples;
8322      * onto fragmented ones */
8323     g_assert (qtdemux->fragmented);
8324     goto done;
8325   }
8326
8327   /* pointer to the sample table */
8328   samples = stream->samples;
8329
8330   /* starts from -1, moves to the next sample index to parse */
8331   stream->stbl_index++;
8332
8333   /* keep track of the first and last sample to fill */
8334   first = &samples[stream->stbl_index];
8335   last = &samples[n];
8336
8337   if (!stream->chunks_are_samples) {
8338     /* set the sample sizes */
8339     if (stream->sample_size == 0) {
8340       /* different sizes for each sample */
8341       for (cur = first; cur <= last; cur++) {
8342         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8343         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8344             (guint) (cur - samples), cur->size);
8345       }
8346     } else {
8347       /* samples have the same size */
8348       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8349       for (cur = first; cur <= last; cur++)
8350         cur->size = stream->sample_size;
8351     }
8352   }
8353
8354   n_samples_per_chunk = stream->n_samples_per_chunk;
8355   cur = first;
8356
8357   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8358     guint32 last_chunk;
8359
8360     if (stream->stsc_chunk_index >= stream->last_chunk
8361         || stream->stsc_chunk_index < stream->first_chunk) {
8362       stream->first_chunk =
8363           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8364       stream->samples_per_chunk =
8365           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8366       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
8367
8368       /* chunk numbers are counted from 1 it seems */
8369       if (G_UNLIKELY (stream->first_chunk == 0))
8370         goto corrupt_file;
8371
8372       --stream->first_chunk;
8373
8374       /* the last chunk of each entry is calculated by taking the first chunk
8375        * of the next entry; except if there is no next, where we fake it with
8376        * INT_MAX */
8377       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8378         stream->last_chunk = G_MAXUINT32;
8379       } else {
8380         stream->last_chunk =
8381             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8382         if (G_UNLIKELY (stream->last_chunk == 0))
8383           goto corrupt_file;
8384
8385         --stream->last_chunk;
8386       }
8387
8388       GST_LOG_OBJECT (qtdemux,
8389           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
8390           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
8391
8392       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8393         goto corrupt_file;
8394
8395       if (stream->last_chunk != G_MAXUINT32) {
8396         if (!qt_atom_parser_peek_sub (&stream->stco,
8397                 stream->first_chunk * stream->co_size,
8398                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8399                 &stream->co_chunk))
8400           goto corrupt_file;
8401
8402       } else {
8403         stream->co_chunk = stream->stco;
8404         if (!gst_byte_reader_skip (&stream->co_chunk,
8405                 stream->first_chunk * stream->co_size))
8406           goto corrupt_file;
8407       }
8408
8409       stream->stsc_chunk_index = stream->first_chunk;
8410     }
8411
8412     last_chunk = stream->last_chunk;
8413
8414     if (stream->chunks_are_samples) {
8415       cur = &samples[stream->stsc_chunk_index];
8416
8417       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8418         if (j > n) {
8419           /* save state */
8420           stream->stsc_chunk_index = j;
8421           goto done;
8422         }
8423
8424         cur->offset =
8425             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8426             stream->co_size);
8427
8428         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8429             "%" G_GUINT64_FORMAT, j, cur->offset);
8430
8431         if (stream->samples_per_frame * stream->bytes_per_frame) {
8432           cur->size =
8433               (stream->samples_per_chunk * stream->n_channels) /
8434               stream->samples_per_frame * stream->bytes_per_frame;
8435         } else {
8436           cur->size = stream->samples_per_chunk;
8437         }
8438
8439         GST_DEBUG_OBJECT (qtdemux,
8440             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8441             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8442                     stream->stco_sample_index)), cur->size);
8443
8444         cur->timestamp = stream->stco_sample_index;
8445         cur->duration = stream->samples_per_chunk;
8446         cur->keyframe = TRUE;
8447         cur++;
8448
8449         stream->stco_sample_index += stream->samples_per_chunk;
8450       }
8451       stream->stsc_chunk_index = j;
8452     } else {
8453       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8454         guint32 samples_per_chunk;
8455         guint64 chunk_offset;
8456
8457         if (!stream->stsc_sample_index
8458             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8459                 &stream->chunk_offset))
8460           goto corrupt_file;
8461
8462         samples_per_chunk = stream->samples_per_chunk;
8463         chunk_offset = stream->chunk_offset;
8464
8465         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8466           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8467               G_GUINT64_FORMAT " and size %d",
8468               (guint) (cur - samples), chunk_offset, cur->size);
8469
8470           cur->offset = chunk_offset;
8471           chunk_offset += cur->size;
8472           cur++;
8473
8474           if (G_UNLIKELY (cur > last)) {
8475             /* save state */
8476             stream->stsc_sample_index = k + 1;
8477             stream->chunk_offset = chunk_offset;
8478             stream->stsc_chunk_index = j;
8479             goto done2;
8480           }
8481         }
8482         stream->stsc_sample_index = 0;
8483       }
8484       stream->stsc_chunk_index = j;
8485     }
8486     stream->stsc_index++;
8487   }
8488
8489   if (stream->chunks_are_samples)
8490     goto ctts;
8491 done2:
8492   {
8493     guint32 n_sample_times;
8494
8495     n_sample_times = stream->n_sample_times;
8496     cur = first;
8497
8498     for (i = stream->stts_index; i < n_sample_times; i++) {
8499       guint32 stts_samples;
8500       gint32 stts_duration;
8501       gint64 stts_time;
8502
8503       if (stream->stts_sample_index >= stream->stts_samples
8504           || !stream->stts_sample_index) {
8505
8506         stream->stts_samples =
8507             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8508         stream->stts_duration =
8509             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8510
8511         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8512             i, stream->stts_samples, stream->stts_duration);
8513
8514         stream->stts_sample_index = 0;
8515       }
8516
8517       stts_samples = stream->stts_samples;
8518       stts_duration = stream->stts_duration;
8519       stts_time = stream->stts_time;
8520
8521       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8522         GST_DEBUG_OBJECT (qtdemux,
8523             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8524             (guint) (cur - samples), j,
8525             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8526
8527         cur->timestamp = stts_time;
8528         cur->duration = stts_duration;
8529
8530         /* avoid 32-bit wrap-around,
8531          * but still mind possible 'negative' duration */
8532         stts_time += (gint64) stts_duration;
8533         cur++;
8534
8535         if (G_UNLIKELY (cur > last)) {
8536           /* save values */
8537           stream->stts_time = stts_time;
8538           stream->stts_sample_index = j + 1;
8539           goto done3;
8540         }
8541       }
8542       stream->stts_sample_index = 0;
8543       stream->stts_time = stts_time;
8544       stream->stts_index++;
8545     }
8546     /* fill up empty timestamps with the last timestamp, this can happen when
8547      * the last samples do not decode and so we don't have timestamps for them.
8548      * We however look at the last timestamp to estimate the track length so we
8549      * need something in here. */
8550     for (; cur < last; cur++) {
8551       GST_DEBUG_OBJECT (qtdemux,
8552           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8553           (guint) (cur - samples),
8554           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8555       cur->timestamp = stream->stts_time;
8556       cur->duration = -1;
8557     }
8558   }
8559 done3:
8560   {
8561     /* sample sync, can be NULL */
8562     if (stream->stss_present == TRUE) {
8563       guint32 n_sample_syncs;
8564
8565       n_sample_syncs = stream->n_sample_syncs;
8566
8567       if (!n_sample_syncs) {
8568         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8569         stream->all_keyframe = TRUE;
8570       } else {
8571         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8572           /* note that the first sample is index 1, not 0 */
8573           guint32 index;
8574
8575           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8576
8577           if (G_LIKELY (index > 0 && index <= n_samples)) {
8578             index -= 1;
8579             samples[index].keyframe = TRUE;
8580             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8581             /* and exit if we have enough samples */
8582             if (G_UNLIKELY (index >= n)) {
8583               i++;
8584               break;
8585             }
8586           }
8587         }
8588         /* save state */
8589         stream->stss_index = i;
8590       }
8591
8592       /* stps marks partial sync frames like open GOP I-Frames */
8593       if (stream->stps_present == TRUE) {
8594         guint32 n_sample_partial_syncs;
8595
8596         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8597
8598         /* if there are no entries, the stss table contains the real
8599          * sync samples */
8600         if (n_sample_partial_syncs) {
8601           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8602             /* note that the first sample is index 1, not 0 */
8603             guint32 index;
8604
8605             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8606
8607             if (G_LIKELY (index > 0 && index <= n_samples)) {
8608               index -= 1;
8609               samples[index].keyframe = TRUE;
8610               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8611               /* and exit if we have enough samples */
8612               if (G_UNLIKELY (index >= n)) {
8613                 i++;
8614                 break;
8615               }
8616             }
8617           }
8618           /* save state */
8619           stream->stps_index = i;
8620         }
8621       }
8622     } else {
8623       /* no stss, all samples are keyframes */
8624       stream->all_keyframe = TRUE;
8625       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8626     }
8627   }
8628
8629 ctts:
8630   /* composition time to sample */
8631   if (stream->ctts_present == TRUE) {
8632     guint32 n_composition_times;
8633     guint32 ctts_count;
8634     gint32 ctts_soffset;
8635
8636     /* Fill in the pts_offsets */
8637     cur = first;
8638     n_composition_times = stream->n_composition_times;
8639
8640     for (i = stream->ctts_index; i < n_composition_times; i++) {
8641       if (stream->ctts_sample_index >= stream->ctts_count
8642           || !stream->ctts_sample_index) {
8643         stream->ctts_count =
8644             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8645         stream->ctts_soffset =
8646             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8647         stream->ctts_sample_index = 0;
8648       }
8649
8650       ctts_count = stream->ctts_count;
8651       ctts_soffset = stream->ctts_soffset;
8652
8653       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8654         cur->pts_offset = ctts_soffset;
8655         cur++;
8656
8657         if (G_UNLIKELY (cur > last)) {
8658           /* save state */
8659           stream->ctts_sample_index = j + 1;
8660           goto done;
8661         }
8662       }
8663       stream->ctts_sample_index = 0;
8664       stream->ctts_index++;
8665     }
8666   }
8667 done:
8668   stream->stbl_index = n;
8669   /* if index has been completely parsed, free data that is no-longer needed */
8670   if (n + 1 == stream->n_samples) {
8671     gst_qtdemux_stbl_free (stream);
8672     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8673     if (qtdemux->pullbased) {
8674       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8675       while (n + 1 == stream->n_samples)
8676         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8677           break;
8678     }
8679   }
8680   GST_OBJECT_UNLOCK (qtdemux);
8681
8682   return TRUE;
8683
8684   /* SUCCESS */
8685 already_parsed:
8686   {
8687     GST_LOG_OBJECT (qtdemux,
8688         "Tried to parse up to sample %u but this sample has already been parsed",
8689         n);
8690     /* if fragmented, there may be more */
8691     if (qtdemux->fragmented && n == stream->stbl_index)
8692       goto done;
8693     GST_OBJECT_UNLOCK (qtdemux);
8694     return TRUE;
8695   }
8696   /* ERRORS */
8697 out_of_samples:
8698   {
8699     GST_LOG_OBJECT (qtdemux,
8700         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8701         stream->n_samples);
8702     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8703         (_("This file is corrupt and cannot be played.")), (NULL));
8704     return FALSE;
8705   }
8706 corrupt_file:
8707   {
8708     GST_OBJECT_UNLOCK (qtdemux);
8709     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8710         (_("This file is corrupt and cannot be played.")), (NULL));
8711     return FALSE;
8712   }
8713 }
8714
8715 /* collect all segment info for @stream.
8716  */
8717 static gboolean
8718 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8719     GNode * trak)
8720 {
8721   GNode *edts;
8722   /* accept edts if they contain gaps at start and there is only
8723    * one media segment */
8724   gboolean allow_pushbased_edts = TRUE;
8725   gint media_segments_count = 0;
8726
8727   /* parse and prepare segment info from the edit list */
8728   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8729   stream->n_segments = 0;
8730   stream->segments = NULL;
8731   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8732     GNode *elst;
8733     gint n_segments;
8734     gint i, count, entry_size;
8735     guint64 time;
8736     GstClockTime stime;
8737     const guint8 *buffer;
8738     guint8 version;
8739     guint32 size;
8740
8741     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8742     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8743       goto done;
8744
8745     buffer = elst->data;
8746
8747     size = QT_UINT32 (buffer);
8748     /* version, flags, n_segments */
8749     if (size < 16) {
8750       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8751       goto done;
8752     }
8753     version = QT_UINT8 (buffer + 8);
8754     entry_size = (version == 1) ? 20 : 12;
8755
8756     n_segments = QT_UINT32 (buffer + 12);
8757
8758     if (size < 16 + n_segments * entry_size) {
8759       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8760       goto done;
8761     }
8762
8763     /* we might allocate a bit too much, at least allocate 1 segment */
8764     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8765
8766     /* segments always start from 0 */
8767     time = 0;
8768     stime = 0;
8769     count = 0;
8770     buffer += 16;
8771     for (i = 0; i < n_segments; i++) {
8772       guint64 duration;
8773       guint64 media_time;
8774       gboolean time_valid = TRUE;
8775       QtDemuxSegment *segment;
8776       guint32 rate_int;
8777       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8778
8779       if (version == 1) {
8780         media_time = QT_UINT64 (buffer + 8);
8781         duration = QT_UINT64 (buffer);
8782         if (media_time == G_MAXUINT64)
8783           time_valid = FALSE;
8784       } else {
8785         media_time = QT_UINT32 (buffer + 4);
8786         duration = QT_UINT32 (buffer);
8787         if (media_time == G_MAXUINT32)
8788           time_valid = FALSE;
8789       }
8790
8791       if (time_valid)
8792         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8793
8794       segment = &stream->segments[count++];
8795
8796       /* time and duration expressed in global timescale */
8797       segment->time = stime;
8798       /* add non scaled values so we don't cause roundoff errors */
8799       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8800         time += duration;
8801         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8802         segment->duration = stime - segment->time;
8803       } else {
8804         /* zero duration does not imply media_start == media_stop
8805          * but, only specify media_start.*/
8806         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8807         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8808             && stime >= media_start) {
8809           segment->duration = stime - media_start;
8810         } else {
8811           segment->duration = GST_CLOCK_TIME_NONE;
8812         }
8813       }
8814       segment->stop_time = stime;
8815
8816       segment->trak_media_start = media_time;
8817       /* media_time expressed in stream timescale */
8818       if (time_valid) {
8819         segment->media_start = media_start;
8820         segment->media_stop = segment->media_start + segment->duration;
8821         media_segments_count++;
8822       } else {
8823         segment->media_start = GST_CLOCK_TIME_NONE;
8824         segment->media_stop = GST_CLOCK_TIME_NONE;
8825       }
8826       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
8827
8828       if (rate_int <= 1) {
8829         /* 0 is not allowed, some programs write 1 instead of the floating point
8830          * value */
8831         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
8832             rate_int);
8833         segment->rate = 1;
8834       } else {
8835         segment->rate = rate_int / 65536.0;
8836       }
8837
8838       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
8839           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
8840           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
8841           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
8842           i, GST_TIME_ARGS (segment->time),
8843           GST_TIME_ARGS (segment->duration),
8844           GST_TIME_ARGS (segment->media_start), media_time,
8845           GST_TIME_ARGS (segment->media_stop),
8846           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
8847           stream->timescale);
8848       if (segment->stop_time > qtdemux->segment.stop) {
8849         GST_WARNING_OBJECT (qtdemux, "Segment %d "
8850             " extends to %" GST_TIME_FORMAT
8851             " past the end of the file duration %" GST_TIME_FORMAT
8852             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
8853             GST_TIME_ARGS (qtdemux->segment.stop));
8854         qtdemux->segment.stop = segment->stop_time;
8855       }
8856
8857       buffer += entry_size;
8858     }
8859     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
8860     stream->n_segments = count;
8861     if (media_segments_count != 1)
8862       allow_pushbased_edts = FALSE;
8863   }
8864 done:
8865
8866   /* push based does not handle segments, so act accordingly here,
8867    * and warn if applicable */
8868   if (!qtdemux->pullbased && !allow_pushbased_edts) {
8869     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
8870     /* remove and use default one below, we stream like it anyway */
8871     g_free (stream->segments);
8872     stream->segments = NULL;
8873     stream->n_segments = 0;
8874   }
8875
8876   /* no segments, create one to play the complete trak */
8877   if (stream->n_segments == 0) {
8878     GstClockTime stream_duration =
8879         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
8880
8881     if (stream->segments == NULL)
8882       stream->segments = g_new (QtDemuxSegment, 1);
8883
8884     /* represent unknown our way */
8885     if (stream_duration == 0)
8886       stream_duration = GST_CLOCK_TIME_NONE;
8887
8888     stream->segments[0].time = 0;
8889     stream->segments[0].stop_time = stream_duration;
8890     stream->segments[0].duration = stream_duration;
8891     stream->segments[0].media_start = 0;
8892     stream->segments[0].media_stop = stream_duration;
8893     stream->segments[0].rate = 1.0;
8894     stream->segments[0].trak_media_start = 0;
8895
8896     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
8897         GST_TIME_ARGS (stream_duration));
8898     stream->n_segments = 1;
8899     stream->dummy_segment = TRUE;
8900   }
8901   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
8902
8903   return TRUE;
8904 }
8905
8906 /*
8907  * Parses the stsd atom of a svq3 trak looking for
8908  * the SMI and gama atoms.
8909  */
8910 static void
8911 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8912     guint8 ** gamma, GstBuffer ** seqh)
8913 {
8914   guint8 *_gamma = NULL;
8915   GstBuffer *_seqh = NULL;
8916   guint8 *stsd_data = stsd->data;
8917   guint32 length = QT_UINT32 (stsd_data);
8918   guint16 version;
8919
8920   if (length < 32) {
8921     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8922     goto end;
8923   }
8924
8925   stsd_data += 32;
8926   length -= 32;
8927   version = QT_UINT16 (stsd_data);
8928   if (version == 3) {
8929     if (length >= 70) {
8930       length -= 70;
8931       stsd_data += 70;
8932       while (length > 8) {
8933         guint32 fourcc, size;
8934         guint8 *data;
8935         size = QT_UINT32 (stsd_data);
8936         fourcc = QT_FOURCC (stsd_data + 4);
8937         data = stsd_data + 8;
8938
8939         if (size == 0) {
8940           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8941               "svq3 atom parsing");
8942           goto end;
8943         }
8944
8945         switch (fourcc) {
8946           case FOURCC_gama:{
8947             if (size == 12) {
8948               _gamma = data;
8949             } else {
8950               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8951                   " for gama atom, expected 12", size);
8952             }
8953             break;
8954           }
8955           case FOURCC_SMI_:{
8956             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8957               guint32 seqh_size;
8958               if (_seqh != NULL) {
8959                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8960                     " found, ignoring");
8961               } else {
8962                 seqh_size = QT_UINT32 (data + 4);
8963                 if (seqh_size > 0) {
8964                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8965                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8966                 }
8967               }
8968             }
8969             break;
8970           }
8971           default:{
8972             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8973                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8974           }
8975         }
8976
8977         if (size <= length) {
8978           length -= size;
8979           stsd_data += size;
8980         }
8981       }
8982     } else {
8983       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8984     }
8985   } else {
8986     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8987         G_GUINT16_FORMAT, version);
8988     goto end;
8989   }
8990
8991 end:
8992   if (gamma) {
8993     *gamma = _gamma;
8994   }
8995   if (seqh) {
8996     *seqh = _seqh;
8997   } else if (_seqh) {
8998     gst_buffer_unref (_seqh);
8999   }
9000 }
9001
9002 static gchar *
9003 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9004 {
9005   GNode *dinf;
9006   GstByteReader dref;
9007   gchar *uri = NULL;
9008
9009   /*
9010    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9011    * atom that might contain a 'data' atom with the rtsp uri.
9012    * This case was reported in bug #597497, some info about
9013    * the hndl atom can be found in TN1195
9014    */
9015   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9016   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9017
9018   if (dinf) {
9019     guint32 dref_num_entries = 0;
9020     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9021         gst_byte_reader_skip (&dref, 4) &&
9022         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9023       gint i;
9024
9025       /* search dref entries for hndl atom */
9026       for (i = 0; i < dref_num_entries; i++) {
9027         guint32 size = 0, type;
9028         guint8 string_len = 0;
9029         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9030             qt_atom_parser_get_fourcc (&dref, &type)) {
9031           if (type == FOURCC_hndl) {
9032             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9033
9034             /* skip data reference handle bytes and the
9035              * following pascal string and some extra 4
9036              * bytes I have no idea what are */
9037             if (!gst_byte_reader_skip (&dref, 4) ||
9038                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9039                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9040               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9041               break;
9042             }
9043
9044             /* iterate over the atoms to find the data atom */
9045             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9046               guint32 atom_size;
9047               guint32 atom_type;
9048
9049               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9050                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9051                 if (atom_type == FOURCC_data) {
9052                   const guint8 *uri_aux = NULL;
9053
9054                   /* found the data atom that might contain the rtsp uri */
9055                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9056                       "hndl atom, interpreting it as an URI");
9057                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9058                           &uri_aux)) {
9059                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9060                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9061                     else
9062                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9063                           "didn't contain a rtsp address");
9064                   } else {
9065                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9066                         "atom contents");
9067                   }
9068                   break;
9069                 }
9070                 /* skipping to the next entry */
9071                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9072                   break;
9073               } else {
9074                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9075                     "atom header");
9076                 break;
9077               }
9078             }
9079             break;
9080           }
9081           /* skip to the next entry */
9082           if (!gst_byte_reader_skip (&dref, size - 8))
9083             break;
9084         } else {
9085           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9086         }
9087       }
9088       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9089     }
9090   }
9091   return uri;
9092 }
9093
9094 #define AMR_NB_ALL_MODES        0x81ff
9095 #define AMR_WB_ALL_MODES        0x83ff
9096 static guint
9097 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9098 {
9099   /* The 'damr' atom is of the form:
9100    *
9101    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9102    *    32 b       8 b          16 b           8 b                 8 b
9103    *
9104    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9105    * represents the highest mode used in the stream (and thus the maximum
9106    * bitrate), with a couple of special cases as seen below.
9107    */
9108
9109   /* Map of frame type ID -> bitrate */
9110   static const guint nb_bitrates[] = {
9111     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9112   };
9113   static const guint wb_bitrates[] = {
9114     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9115   };
9116   GstMapInfo map;
9117   gsize max_mode;
9118   guint16 mode_set;
9119
9120   gst_buffer_map (buf, &map, GST_MAP_READ);
9121
9122   if (map.size != 0x11) {
9123     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9124     goto bad_data;
9125   }
9126
9127   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9128     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9129         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9130     goto bad_data;
9131   }
9132
9133   mode_set = QT_UINT16 (map.data + 13);
9134
9135   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9136     max_mode = 7 + (wb ? 1 : 0);
9137   else
9138     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9139     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9140
9141   if (max_mode == -1) {
9142     GST_DEBUG ("No mode indication was found (mode set) = %x",
9143         (guint) mode_set);
9144     goto bad_data;
9145   }
9146
9147   gst_buffer_unmap (buf, &map);
9148   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9149
9150 bad_data:
9151   gst_buffer_unmap (buf, &map);
9152   return 0;
9153 }
9154
9155 static gboolean
9156 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9157     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9158 {
9159   /*
9160    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9161    * [0 1 2]
9162    * [3 4 5]
9163    * [6 7 8]
9164    */
9165
9166   if (gst_byte_reader_get_remaining (reader) < 36)
9167     return FALSE;
9168
9169   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9170   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9171   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9172   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9173   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9174   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9175   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9176   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9177   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9178
9179   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9180   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9181       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9182       matrix[2] & 0xFF);
9183   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9184       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9185       matrix[5] & 0xFF);
9186   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9187       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9188       matrix[8] & 0xFF);
9189
9190   return TRUE;
9191 }
9192
9193 static void
9194 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9195     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9196 {
9197
9198 /* [a b c]
9199  * [d e f]
9200  * [g h i]
9201  *
9202  * This macro will only compare value abdegh, it expects cfi to have already
9203  * been checked
9204  */
9205 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9206                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9207
9208   /* only handle the cases where the last column has standard values */
9209   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9210     const gchar *rotation_tag = NULL;
9211
9212     /* no rotation needed */
9213     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9214       /* NOP */
9215     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9216       rotation_tag = "rotate-90";
9217     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9218       rotation_tag = "rotate-180";
9219     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9220       rotation_tag = "rotate-270";
9221     } else {
9222       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9223     }
9224
9225     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9226         rotation_tag);
9227     if (rotation_tag != NULL) {
9228       if (*taglist == NULL)
9229         *taglist = gst_tag_list_new_empty ();
9230       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9231           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9232     }
9233   } else {
9234     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9235   }
9236 }
9237
9238 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9239  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9240  * Common Encryption (cenc), the function will also parse the tenc box (defined
9241  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9242  * (typically an enc[v|a|t|s] sample entry); the function will set
9243  * @original_fmt to the fourcc of the original unencrypted stream format.
9244  * Returns TRUE if successful; FALSE otherwise. */
9245 static gboolean
9246 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9247     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9248 {
9249   GNode *sinf;
9250   GNode *frma;
9251   GNode *schm;
9252   GNode *schi;
9253
9254   g_return_val_if_fail (qtdemux != NULL, FALSE);
9255   g_return_val_if_fail (stream != NULL, FALSE);
9256   g_return_val_if_fail (container != NULL, FALSE);
9257   g_return_val_if_fail (original_fmt != NULL, FALSE);
9258
9259   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9260   if (G_UNLIKELY (!sinf)) {
9261     if (stream->protection_scheme_type == FOURCC_cenc) {
9262       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9263           "mandatory for Common Encryption");
9264       return FALSE;
9265     }
9266     return TRUE;
9267   }
9268
9269   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9270   if (G_UNLIKELY (!frma)) {
9271     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9272     return FALSE;
9273   }
9274
9275   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9276   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9277       GST_FOURCC_ARGS (*original_fmt));
9278
9279   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9280   if (!schm) {
9281     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9282     return FALSE;
9283   }
9284   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9285   stream->protection_scheme_version =
9286       QT_UINT32 ((const guint8 *) schm->data + 16);
9287
9288   GST_DEBUG_OBJECT (qtdemux,
9289       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9290       "protection_scheme_version: %#010x",
9291       GST_FOURCC_ARGS (stream->protection_scheme_type),
9292       stream->protection_scheme_version);
9293
9294   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9295   if (!schi) {
9296     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9297     return FALSE;
9298   }
9299   if (stream->protection_scheme_type == FOURCC_cenc) {
9300     QtDemuxCencSampleSetInfo *info;
9301     GNode *tenc;
9302     const guint8 *tenc_data;
9303     guint32 isEncrypted;
9304     guint8 iv_size;
9305     const guint8 *default_kid;
9306     GstBuffer *kid_buf;
9307
9308     if (G_UNLIKELY (!stream->protection_scheme_info))
9309       stream->protection_scheme_info =
9310           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9311
9312     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9313
9314     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9315     if (!tenc) {
9316       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9317           "which is mandatory for Common Encryption");
9318       return FALSE;
9319     }
9320     tenc_data = (const guint8 *) tenc->data + 12;
9321     isEncrypted = QT_UINT24 (tenc_data);
9322     iv_size = QT_UINT8 (tenc_data + 3);
9323     default_kid = (tenc_data + 4);
9324     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9325     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9326     if (info->default_properties)
9327       gst_structure_free (info->default_properties);
9328     info->default_properties =
9329         gst_structure_new ("application/x-cenc",
9330         "iv_size", G_TYPE_UINT, iv_size,
9331         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9332         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9333     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9334         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9335     gst_buffer_unref (kid_buf);
9336   }
9337   return TRUE;
9338 }
9339
9340 /* parse the traks.
9341  * With each track we associate a new QtDemuxStream that contains all the info
9342  * about the trak.
9343  * traks that do not decode to something (like strm traks) will not have a pad.
9344  */
9345 static gboolean
9346 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9347 {
9348   GstByteReader tkhd;
9349   int offset;
9350   GNode *mdia;
9351   GNode *mdhd;
9352   GNode *hdlr;
9353   GNode *minf;
9354   GNode *stbl;
9355   GNode *stsd;
9356   GNode *mp4a;
9357   GNode *mp4v;
9358   GNode *wave;
9359   GNode *esds;
9360   GNode *pasp;
9361   GNode *colr;
9362   GNode *tref;
9363   GNode *udta;
9364   GNode *svmi;
9365   GNode *fiel;
9366
9367   QtDemuxStream *stream = NULL;
9368   gboolean new_stream = FALSE;
9369   gchar *codec = NULL;
9370   const guint8 *stsd_data;
9371   guint16 lang_code;            /* quicktime lang code or packed iso code */
9372   guint32 version;
9373   guint32 tkhd_flags = 0;
9374   guint8 tkhd_version = 0;
9375   guint32 fourcc;
9376   guint value_size, stsd_len, len;
9377   guint32 track_id;
9378   guint32 dummy;
9379
9380   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9381
9382   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9383       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9384       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9385     goto corrupt_file;
9386
9387   /* pick between 64 or 32 bits */
9388   value_size = tkhd_version == 1 ? 8 : 4;
9389   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9390       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9391     goto corrupt_file;
9392
9393   if (!qtdemux->got_moov) {
9394     if (qtdemux_find_stream (qtdemux, track_id))
9395       goto existing_stream;
9396     stream = _create_stream ();
9397     stream->track_id = track_id;
9398     new_stream = TRUE;
9399   } else {
9400     stream = qtdemux_find_stream (qtdemux, track_id);
9401     if (!stream) {
9402       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9403       goto skip_track;
9404     }
9405
9406     /* flush samples data from this track from previous moov */
9407     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9408     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9409   }
9410   /* need defaults for fragments */
9411   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9412
9413   if (stream->pending_tags == NULL)
9414     stream->pending_tags = gst_tag_list_new_empty ();
9415
9416   if ((tkhd_flags & 1) == 0)
9417     stream->disabled = TRUE;
9418
9419   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9420       tkhd_version, tkhd_flags, stream->track_id);
9421
9422   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9423     goto corrupt_file;
9424
9425   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9426     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9427     if (qtdemux->major_brand != FOURCC_mjp2 ||
9428         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9429       goto corrupt_file;
9430   }
9431
9432   len = QT_UINT32 ((guint8 *) mdhd->data);
9433   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9434   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9435   if (version == 0x01000000) {
9436     if (len < 38)
9437       goto corrupt_file;
9438     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9439     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9440     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9441   } else {
9442     if (len < 30)
9443       goto corrupt_file;
9444     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9445     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9446     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9447   }
9448
9449   if (lang_code < 0x400) {
9450     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9451   } else if (lang_code == 0x7fff) {
9452     stream->lang_id[0] = 0;     /* unspecified */
9453   } else {
9454     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9455     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9456     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9457     stream->lang_id[3] = 0;
9458   }
9459
9460   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9461       stream->timescale);
9462   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9463       stream->duration);
9464   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9465       lang_code, stream->lang_id);
9466
9467   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9468     goto corrupt_file;
9469
9470   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9471     /* chapters track reference */
9472     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9473     if (chap) {
9474       gsize length = GST_READ_UINT32_BE (chap->data);
9475       if (qtdemux->chapters_track_id)
9476         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9477
9478       if (length >= 12) {
9479         qtdemux->chapters_track_id =
9480             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9481       }
9482     }
9483   }
9484
9485   /* fragmented files may have bogus duration in moov */
9486   if (!qtdemux->fragmented &&
9487       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9488     guint64 tdur1, tdur2;
9489
9490     /* don't overflow */
9491     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9492     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9493
9494     /* HACK:
9495      * some of those trailers, nowadays, have prologue images that are
9496      * themselves video tracks as well. I haven't really found a way to
9497      * identify those yet, except for just looking at their duration. */
9498     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9499       GST_WARNING_OBJECT (qtdemux,
9500           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9501           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9502           "found, assuming preview image or something; skipping track",
9503           stream->duration, stream->timescale, qtdemux->duration,
9504           qtdemux->timescale);
9505       if (new_stream)
9506         gst_qtdemux_stream_free (qtdemux, stream);
9507       return TRUE;
9508     }
9509   }
9510
9511   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9512     goto corrupt_file;
9513
9514   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9515       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9516
9517   len = QT_UINT32 ((guint8 *) hdlr->data);
9518   if (len >= 20)
9519     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9520   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9521       GST_FOURCC_ARGS (stream->subtype));
9522
9523   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9524     goto corrupt_file;
9525
9526   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9527     goto corrupt_file;
9528
9529   /*parse svmi header if existing */
9530   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9531   if (svmi) {
9532     len = QT_UINT32 ((guint8 *) svmi->data);
9533     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9534     if (!version) {
9535       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9536       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9537       guint8 frame_type, frame_layout;
9538
9539       /* MPEG-A stereo video */
9540       if (qtdemux->major_brand == FOURCC_ss02)
9541         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9542
9543       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9544       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9545       switch (frame_type) {
9546         case 0:
9547           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9548           break;
9549         case 1:
9550           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9551           break;
9552         case 2:
9553           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9554           break;
9555         case 3:
9556           /* mode 3 is primary/secondary view sequence, ie
9557            * left/right views in separate tracks. See section 7.2
9558            * of ISO/IEC 23000-11:2009 */
9559           GST_FIXME_OBJECT (qtdemux,
9560               "Implement stereo video in separate streams");
9561       }
9562
9563       if ((frame_layout & 0x1) == 0)
9564         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9565
9566       GST_LOG_OBJECT (qtdemux,
9567           "StereoVideo: composition type: %u, is_left_first: %u",
9568           frame_type, frame_layout);
9569       stream->multiview_mode = mode;
9570       stream->multiview_flags = flags;
9571     }
9572   }
9573
9574   /* parse stsd */
9575   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9576     goto corrupt_file;
9577   stsd_data = (const guint8 *) stsd->data;
9578
9579   /* stsd should at least have one entry */
9580   stsd_len = QT_UINT32 (stsd_data);
9581   if (stsd_len < 24) {
9582     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9583     if (stream->subtype == FOURCC_vivo) {
9584       if (new_stream)
9585         gst_qtdemux_stream_free (qtdemux, stream);
9586       return TRUE;
9587     } else {
9588       goto corrupt_file;
9589     }
9590   }
9591
9592   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9593
9594   /* and that entry should fit within stsd */
9595   len = QT_UINT32 (stsd_data + 16);
9596   if (len > stsd_len + 16)
9597     goto corrupt_file;
9598
9599   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
9600   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9601       GST_FOURCC_ARGS (stream->fourcc));
9602   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9603
9604   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9605     goto error_encrypted;
9606
9607   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9608     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9609     stream->protected = TRUE;
9610     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9611       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9612   }
9613
9614   if (stream->subtype == FOURCC_vide) {
9615     guint32 w = 0, h = 0;
9616     gboolean gray;
9617     gint depth, palette_size, palette_count;
9618     guint32 matrix[9];
9619     guint32 *palette_data = NULL;
9620
9621     stream->sampled = TRUE;
9622
9623     /* version 1 uses some 64-bit ints */
9624     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9625       goto corrupt_file;
9626
9627     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9628       goto corrupt_file;
9629
9630     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9631         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9632       goto corrupt_file;
9633
9634     stream->display_width = w >> 16;
9635     stream->display_height = h >> 16;
9636
9637     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9638         &stream->pending_tags);
9639
9640     offset = 16;
9641     if (len < 86)
9642       goto corrupt_file;
9643
9644     stream->width = QT_UINT16 (stsd_data + offset + 32);
9645     stream->height = QT_UINT16 (stsd_data + offset + 34);
9646     stream->fps_n = 0;          /* this is filled in later */
9647     stream->fps_d = 0;          /* this is filled in later */
9648     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
9649     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
9650
9651     /* if color_table_id is 0, ctab atom must follow; however some files
9652      * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9653      * if color table is not present we'll correct the value */
9654     if (stream->color_table_id == 0 &&
9655         (len < 90 || QT_FOURCC (stsd_data + offset + 86) != FOURCC_ctab)) {
9656       stream->color_table_id = -1;
9657     }
9658
9659     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9660         stream->width, stream->height, stream->bits_per_sample,
9661         stream->color_table_id);
9662
9663     depth = stream->bits_per_sample;
9664
9665     /* more than 32 bits means grayscale */
9666     gray = (depth > 32);
9667     /* low 32 bits specify the depth  */
9668     depth &= 0x1F;
9669
9670     /* different number of palette entries is determined by depth. */
9671     palette_count = 0;
9672     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9673       palette_count = (1 << depth);
9674     palette_size = palette_count * 4;
9675
9676     if (stream->color_table_id) {
9677       switch (palette_count) {
9678         case 0:
9679           break;
9680         case 2:
9681           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9682           break;
9683         case 4:
9684           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9685           break;
9686         case 16:
9687           if (gray)
9688             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
9689           else
9690             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9691           break;
9692         case 256:
9693           if (gray)
9694             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
9695           else
9696             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9697           break;
9698         default:
9699           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9700               (_("The video in this file might not play correctly.")),
9701               ("unsupported palette depth %d", depth));
9702           break;
9703       }
9704     } else {
9705       gint i, j, start, end;
9706
9707       if (len < 94)
9708         goto corrupt_file;
9709
9710       /* read table */
9711       start = QT_UINT32 (stsd_data + offset + 86);
9712       palette_count = QT_UINT16 (stsd_data + offset + 90);
9713       end = QT_UINT16 (stsd_data + offset + 92);
9714
9715       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9716           start, end, palette_count);
9717
9718       if (end > 255)
9719         end = 255;
9720       if (start > end)
9721         start = end;
9722
9723       if (len < 94 + (end - start) * 8)
9724         goto corrupt_file;
9725
9726       /* palette is always the same size */
9727       palette_data = g_malloc0 (256 * 4);
9728       palette_size = 256 * 4;
9729
9730       for (j = 0, i = start; i <= end; j++, i++) {
9731         guint32 a, r, g, b;
9732
9733         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
9734         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
9735         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
9736         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
9737
9738         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9739             (g & 0xff00) | (b >> 8);
9740       }
9741     }
9742
9743     if (stream->caps)
9744       gst_caps_unref (stream->caps);
9745
9746     stream->caps =
9747         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
9748     if (G_UNLIKELY (!stream->caps)) {
9749       g_free (palette_data);
9750       goto unknown_stream;
9751     }
9752
9753     if (codec) {
9754       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9755           GST_TAG_VIDEO_CODEC, codec, NULL);
9756       g_free (codec);
9757       codec = NULL;
9758     }
9759
9760
9761     if (palette_data) {
9762       GstStructure *s;
9763
9764       if (stream->rgb8_palette)
9765         gst_memory_unref (stream->rgb8_palette);
9766       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9767           palette_data, palette_size, 0, palette_size, palette_data, g_free);
9768
9769       s = gst_caps_get_structure (stream->caps, 0);
9770
9771       /* non-raw video has a palette_data property. raw video has the palette as
9772        * an extra plane that we append to the output buffers before we push
9773        * them*/
9774       if (!gst_structure_has_name (s, "video/x-raw")) {
9775         GstBuffer *palette;
9776
9777         palette = gst_buffer_new ();
9778         gst_buffer_append_memory (palette, stream->rgb8_palette);
9779         stream->rgb8_palette = NULL;
9780
9781         gst_caps_set_simple (stream->caps, "palette_data",
9782             GST_TYPE_BUFFER, palette, NULL);
9783         gst_buffer_unref (palette);
9784       }
9785     } else if (palette_count != 0) {
9786       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9787           (NULL), ("Unsupported palette depth %d", depth));
9788     }
9789
9790     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9791         QT_UINT16 (stsd_data + offset + 48));
9792
9793     esds = NULL;
9794     pasp = NULL;
9795     colr = NULL;
9796     fiel = NULL;
9797     /* pick 'the' stsd child */
9798     if (!stream->protected)
9799       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
9800     else
9801       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
9802
9803     if (mp4v) {
9804       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9805       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
9806       colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
9807       fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
9808     }
9809
9810     if (pasp) {
9811       const guint8 *pasp_data = (const guint8 *) pasp->data;
9812       gint len = QT_UINT32 (pasp_data);
9813
9814       if (len == 16) {
9815         stream->par_w = QT_UINT32 (pasp_data + 8);
9816         stream->par_h = QT_UINT32 (pasp_data + 12);
9817       } else {
9818         stream->par_w = 0;
9819         stream->par_h = 0;
9820       }
9821     } else {
9822       stream->par_w = 0;
9823       stream->par_h = 0;
9824     }
9825
9826     if (fiel) {
9827       const guint8 *fiel_data = (const guint8 *) fiel->data;
9828       gint len = QT_UINT32 (fiel_data);
9829
9830       if (len == 10) {
9831         stream->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
9832         stream->field_order = GST_READ_UINT8 (fiel_data + 9);
9833       }
9834     }
9835
9836     if (colr) {
9837       const guint8 *colr_data = (const guint8 *) colr->data;
9838       gint len = QT_UINT32 (colr_data);
9839
9840       if (len == 19 || len == 18) {
9841         guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
9842
9843         if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
9844           guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
9845           guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
9846           guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
9847           gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
9848
9849           switch (primaries) {
9850             case 1:
9851               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
9852               break;
9853             case 5:
9854               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
9855               break;
9856             case 6:
9857               stream->colorimetry.primaries =
9858                   GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
9859               break;
9860             case 9:
9861               stream->colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
9862               break;
9863             default:
9864               break;
9865           }
9866
9867           switch (transfer_function) {
9868             case 1:
9869               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
9870               break;
9871             case 7:
9872               stream->colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
9873               break;
9874             default:
9875               break;
9876           }
9877
9878           switch (matrix) {
9879             case 1:
9880               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
9881               break;
9882             case 6:
9883               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
9884               break;
9885             case 7:
9886               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
9887               break;
9888             case 9:
9889               stream->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
9890               break;
9891             default:
9892               break;
9893           }
9894
9895           stream->colorimetry.range =
9896               full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
9897               GST_VIDEO_COLOR_RANGE_16_235;
9898         } else {
9899           GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
9900         }
9901       } else {
9902         GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
9903       }
9904     }
9905
9906     if (esds) {
9907       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9908     } else {
9909       switch (fourcc) {
9910         case FOURCC_H264:
9911         case FOURCC_avc1:
9912         case FOURCC_avc3:
9913         {
9914           gint len = QT_UINT32 (stsd_data) - 0x66;
9915           const guint8 *avc_data = stsd_data + 0x66;
9916
9917           /* find avcC */
9918           while (len >= 0x8) {
9919             gint size;
9920
9921             if (QT_UINT32 (avc_data) <= len)
9922               size = QT_UINT32 (avc_data) - 0x8;
9923             else
9924               size = len - 0x8;
9925
9926             if (size < 1)
9927               /* No real data, so break out */
9928               break;
9929
9930             switch (QT_FOURCC (avc_data + 0x4)) {
9931               case FOURCC_avcC:
9932               {
9933                 /* parse, if found */
9934                 GstBuffer *buf;
9935
9936                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9937
9938                 /* First 4 bytes are the length of the atom, the next 4 bytes
9939                  * are the fourcc, the next 1 byte is the version, and the
9940                  * subsequent bytes are profile_tier_level structure like data. */
9941                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9942                     avc_data + 8 + 1, size - 1);
9943                 buf = gst_buffer_new_and_alloc (size);
9944                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
9945                 gst_caps_set_simple (stream->caps,
9946                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9947                 gst_buffer_unref (buf);
9948
9949                 break;
9950               }
9951               case FOURCC_strf:
9952               {
9953                 GstBuffer *buf;
9954
9955                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
9956
9957                 /* First 4 bytes are the length of the atom, the next 4 bytes
9958                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
9959                  * next 1 byte is the version, and the
9960                  * subsequent bytes are sequence parameter set like data. */
9961
9962                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
9963                 if (size > 1) {
9964                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
9965                       avc_data + 8 + 40 + 1, size - 1);
9966
9967                   buf = gst_buffer_new_and_alloc (size);
9968                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
9969                   gst_caps_set_simple (stream->caps,
9970                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
9971                   gst_buffer_unref (buf);
9972                 }
9973                 break;
9974               }
9975               case FOURCC_btrt:
9976               {
9977                 guint avg_bitrate, max_bitrate;
9978
9979                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
9980                 if (size < 12)
9981                   break;
9982
9983                 max_bitrate = QT_UINT32 (avc_data + 0xc);
9984                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
9985
9986                 if (!max_bitrate && !avg_bitrate)
9987                   break;
9988
9989                 /* Some muxers seem to swap the average and maximum bitrates
9990                  * (I'm looking at you, YouTube), so we swap for sanity. */
9991                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
9992                   guint temp = avg_bitrate;
9993
9994                   avg_bitrate = max_bitrate;
9995                   max_bitrate = temp;
9996                 }
9997
9998                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
9999                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10000                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
10001                 }
10002                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10003                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10004                       GST_TAG_BITRATE, avg_bitrate, NULL);
10005                 }
10006
10007                 break;
10008               }
10009
10010               default:
10011                 break;
10012             }
10013
10014             len -= size + 8;
10015             avc_data += size + 8;
10016           }
10017
10018           break;
10019         }
10020         case FOURCC_H265:
10021         case FOURCC_hvc1:
10022         case FOURCC_hev1:
10023         {
10024           gint len = QT_UINT32 (stsd_data) - 0x66;
10025           const guint8 *hevc_data = stsd_data + 0x66;
10026
10027           /* find hevc */
10028           while (len >= 0x8) {
10029             gint size;
10030
10031             if (QT_UINT32 (hevc_data) <= len)
10032               size = QT_UINT32 (hevc_data) - 0x8;
10033             else
10034               size = len - 0x8;
10035
10036             if (size < 1)
10037               /* No real data, so break out */
10038               break;
10039
10040             switch (QT_FOURCC (hevc_data + 0x4)) {
10041               case FOURCC_hvcC:
10042               {
10043                 /* parse, if found */
10044                 GstBuffer *buf;
10045
10046                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10047
10048                 /* First 4 bytes are the length of the atom, the next 4 bytes
10049                  * are the fourcc, the next 1 byte is the version, and the
10050                  * subsequent bytes are sequence parameter set like data. */
10051                 gst_codec_utils_h265_caps_set_level_tier_and_profile
10052                     (stream->caps, hevc_data + 8 + 1, size - 1);
10053
10054                 buf = gst_buffer_new_and_alloc (size);
10055                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10056                 gst_caps_set_simple (stream->caps,
10057                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10058                 gst_buffer_unref (buf);
10059                 break;
10060               }
10061               default:
10062                 break;
10063             }
10064             len -= size + 8;
10065             hevc_data += size + 8;
10066           }
10067           break;
10068         }
10069         case FOURCC_mp4v:
10070         case FOURCC_MP4V:
10071         case FOURCC_fmp4:
10072         case FOURCC_FMP4:
10073         case FOURCC_xvid:
10074         case FOURCC_XVID:
10075         {
10076           GNode *glbl;
10077
10078           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10079               GST_FOURCC_ARGS (fourcc));
10080
10081           /* codec data might be in glbl extension atom */
10082           glbl = mp4v ?
10083               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10084           if (glbl) {
10085             guint8 *data;
10086             GstBuffer *buf;
10087             gint len;
10088
10089             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10090             data = glbl->data;
10091             len = QT_UINT32 (data);
10092             if (len > 0x8) {
10093               len -= 0x8;
10094               buf = gst_buffer_new_and_alloc (len);
10095               gst_buffer_fill (buf, 0, data + 8, len);
10096               gst_caps_set_simple (stream->caps,
10097                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10098               gst_buffer_unref (buf);
10099             }
10100           }
10101           break;
10102         }
10103         case FOURCC_mjp2:
10104         {
10105           /* see annex I of the jpeg2000 spec */
10106           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10107           const guint8 *data;
10108           const gchar *colorspace = NULL;
10109           gint ncomp = 0;
10110           guint32 ncomp_map = 0;
10111           gint32 *comp_map = NULL;
10112           guint32 nchan_def = 0;
10113           gint32 *chan_def = NULL;
10114
10115           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10116           /* some required atoms */
10117           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
10118           if (!mjp2)
10119             break;
10120           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10121           if (!jp2h)
10122             break;
10123
10124           /* number of components; redundant with info in codestream, but useful
10125              to a muxer */
10126           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10127           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10128             break;
10129           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10130
10131           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10132           if (!colr)
10133             break;
10134           GST_DEBUG_OBJECT (qtdemux, "found colr");
10135           /* extract colour space info */
10136           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10137             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10138               case 16:
10139                 colorspace = "sRGB";
10140                 break;
10141               case 17:
10142                 colorspace = "GRAY";
10143                 break;
10144               case 18:
10145                 colorspace = "sYUV";
10146                 break;
10147               default:
10148                 colorspace = NULL;
10149                 break;
10150             }
10151           }
10152           if (!colorspace)
10153             /* colr is required, and only values 16, 17, and 18 are specified,
10154                so error if we have no colorspace */
10155             break;
10156
10157           /* extract component mapping */
10158           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10159           if (cmap) {
10160             guint32 cmap_len = 0;
10161             int i;
10162             cmap_len = QT_UINT32 (cmap->data);
10163             if (cmap_len >= 8) {
10164               /* normal box, subtract off header */
10165               cmap_len -= 8;
10166               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10167               if (cmap_len % 4 == 0) {
10168                 ncomp_map = (cmap_len / 4);
10169                 comp_map = g_new0 (gint32, ncomp_map);
10170                 for (i = 0; i < ncomp_map; i++) {
10171                   guint16 cmp;
10172                   guint8 mtyp, pcol;
10173                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10174                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10175                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10176                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10177                 }
10178               }
10179             }
10180           }
10181           /* extract channel definitions */
10182           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10183           if (cdef) {
10184             guint32 cdef_len = 0;
10185             int i;
10186             cdef_len = QT_UINT32 (cdef->data);
10187             if (cdef_len >= 10) {
10188               /* normal box, subtract off header and len */
10189               cdef_len -= 10;
10190               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10191               if (cdef_len % 6 == 0) {
10192                 nchan_def = (cdef_len / 6);
10193                 chan_def = g_new0 (gint32, nchan_def);
10194                 for (i = 0; i < nchan_def; i++)
10195                   chan_def[i] = -1;
10196                 for (i = 0; i < nchan_def; i++) {
10197                   guint16 cn, typ, asoc;
10198                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10199                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10200                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10201                   if (cn < nchan_def) {
10202                     switch (typ) {
10203                       case 0:
10204                         chan_def[cn] = asoc;
10205                         break;
10206                       case 1:
10207                         chan_def[cn] = 0;       /* alpha */
10208                         break;
10209                       default:
10210                         chan_def[cn] = -typ;
10211                     }
10212                   }
10213                 }
10214               }
10215             }
10216           }
10217
10218           gst_caps_set_simple (stream->caps,
10219               "num-components", G_TYPE_INT, ncomp, NULL);
10220           gst_caps_set_simple (stream->caps,
10221               "colorspace", G_TYPE_STRING, colorspace, NULL);
10222
10223           if (comp_map) {
10224             GValue arr = { 0, };
10225             GValue elt = { 0, };
10226             int i;
10227             g_value_init (&arr, GST_TYPE_ARRAY);
10228             g_value_init (&elt, G_TYPE_INT);
10229             for (i = 0; i < ncomp_map; i++) {
10230               g_value_set_int (&elt, comp_map[i]);
10231               gst_value_array_append_value (&arr, &elt);
10232             }
10233             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10234                 "component-map", &arr);
10235             g_value_unset (&elt);
10236             g_value_unset (&arr);
10237             g_free (comp_map);
10238           }
10239
10240           if (chan_def) {
10241             GValue arr = { 0, };
10242             GValue elt = { 0, };
10243             int i;
10244             g_value_init (&arr, GST_TYPE_ARRAY);
10245             g_value_init (&elt, G_TYPE_INT);
10246             for (i = 0; i < nchan_def; i++) {
10247               g_value_set_int (&elt, chan_def[i]);
10248               gst_value_array_append_value (&arr, &elt);
10249             }
10250             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
10251                 "channel-definitions", &arr);
10252             g_value_unset (&elt);
10253             g_value_unset (&arr);
10254             g_free (chan_def);
10255           }
10256
10257           /* some optional atoms */
10258           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10259           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10260
10261           /* indicate possible fields in caps */
10262           if (field) {
10263             data = (guint8 *) field->data + 8;
10264             if (*data != 1)
10265               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
10266                   (gint) * data, NULL);
10267           }
10268           /* add codec_data if provided */
10269           if (prefix) {
10270             GstBuffer *buf;
10271             gint len;
10272
10273             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10274             data = prefix->data;
10275             len = QT_UINT32 (data);
10276             if (len > 0x8) {
10277               len -= 0x8;
10278               buf = gst_buffer_new_and_alloc (len);
10279               gst_buffer_fill (buf, 0, data + 8, len);
10280               gst_caps_set_simple (stream->caps,
10281                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10282               gst_buffer_unref (buf);
10283             }
10284           }
10285           break;
10286         }
10287         case FOURCC_jpeg:
10288         {
10289           /* https://developer.apple.com/standards/qtff-2001.pdf,
10290            * page 92, "Video Sample Description", under table 3.1 */
10291           GstByteReader br;
10292
10293           const gint compressor_offset = 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10294           const gint min_size = compressor_offset + 32 + 2 + 2;
10295           GNode *jpeg;
10296           guint32 len;
10297           guint16 color_table_id = 0;
10298           gboolean ok;
10299
10300           GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10301
10302           /* recover information on interlaced/progressive */
10303           jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10304           if (!jpeg)
10305             break;
10306
10307           len = QT_UINT32 (jpeg->data);
10308           GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10309               min_size);
10310           if (len >= min_size) {
10311             gst_byte_reader_init (&br, jpeg->data, len);
10312
10313             gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10314             gst_byte_reader_get_uint16_le (&br, &color_table_id);
10315             if (color_table_id != 0) {
10316               /* the spec says there can be concatenated chunks in the data, and we want
10317                * to find one called field. Walk through them. */
10318               gint offset = min_size;
10319               while (offset + 8 < len) {
10320                 guint32 size = 0, tag;
10321                 ok = gst_byte_reader_get_uint32_le (&br, &size);
10322                 ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10323                 if (!ok || size < 8) {
10324                   GST_WARNING_OBJECT (qtdemux,
10325                       "Failed to walk optional chunk list");
10326                   break;
10327                 }
10328                 GST_DEBUG_OBJECT (qtdemux,
10329                     "Found optional %4.4s chunk, size %u", (const char *) &tag,
10330                     size);
10331                 if (tag == FOURCC_fiel) {
10332                   guint8 n_fields, ordering;
10333                   gst_byte_reader_get_uint8 (&br, &n_fields);
10334                   gst_byte_reader_get_uint8 (&br, &ordering);
10335                   if (n_fields == 1 || n_fields == 2) {
10336                     GST_DEBUG_OBJECT (qtdemux,
10337                         "Found fiel tag with %u fields, ordering %u", n_fields,
10338                         ordering);
10339                     if (n_fields == 2)
10340                       gst_caps_set_simple (stream->caps, "interlace-mode",
10341                           G_TYPE_STRING, "interleaved", NULL);
10342                   } else {
10343                     GST_WARNING_OBJECT (qtdemux,
10344                         "Found fiel tag with invalid fields (%u)", n_fields);
10345                   }
10346                 }
10347                 offset += size;
10348               }
10349             } else {
10350               GST_DEBUG_OBJECT (qtdemux,
10351                   "Color table ID is 0, not trying to get interlacedness");
10352             }
10353           } else {
10354             GST_WARNING_OBJECT (qtdemux,
10355                 "Length of jpeg chunk is too small, not trying to get interlacedness");
10356           }
10357
10358           break;
10359         }
10360         case FOURCC_SVQ3:
10361         case FOURCC_VP31:
10362         {
10363           GstBuffer *buf;
10364           GstBuffer *seqh = NULL;
10365           guint8 *gamma_data = NULL;
10366           gint len = QT_UINT32 (stsd_data);
10367
10368           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
10369           if (gamma_data) {
10370             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
10371                 QT_FP32 (gamma_data), NULL);
10372           }
10373           if (seqh) {
10374             /* sorry for the bad name, but we don't know what this is, other
10375              * than its own fourcc */
10376             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
10377                 NULL);
10378             gst_buffer_unref (seqh);
10379           }
10380
10381           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10382           buf = gst_buffer_new_and_alloc (len);
10383           gst_buffer_fill (buf, 0, stsd_data, len);
10384           gst_caps_set_simple (stream->caps,
10385               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10386           gst_buffer_unref (buf);
10387           break;
10388         }
10389         case FOURCC_rle_:
10390         case FOURCC_WRLE:
10391         {
10392           gst_caps_set_simple (stream->caps,
10393               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
10394           break;
10395         }
10396         case FOURCC_XiTh:
10397         {
10398           GNode *xith, *xdxt;
10399
10400           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10401           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
10402           if (!xith)
10403             break;
10404
10405           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10406           if (!xdxt)
10407             break;
10408
10409           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10410           /* collect the headers and store them in a stream list so that we can
10411            * send them out first */
10412           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10413           break;
10414         }
10415         case FOURCC_ovc1:
10416         {
10417           GNode *ovc1;
10418           guint8 *ovc1_data;
10419           guint ovc1_len;
10420           GstBuffer *buf;
10421
10422           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10423           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
10424           if (!ovc1)
10425             break;
10426           ovc1_data = ovc1->data;
10427           ovc1_len = QT_UINT32 (ovc1_data);
10428           if (ovc1_len <= 198) {
10429             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10430             break;
10431           }
10432           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10433           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10434           gst_caps_set_simple (stream->caps,
10435               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10436           gst_buffer_unref (buf);
10437           break;
10438         }
10439         case FOURCC_vc_1:
10440         {
10441           gint len = QT_UINT32 (stsd_data) - 0x66;
10442           const guint8 *vc1_data = stsd_data + 0x66;
10443
10444           /* find dvc1 */
10445           while (len >= 8) {
10446             gint size;
10447
10448             if (QT_UINT32 (vc1_data) <= len)
10449               size = QT_UINT32 (vc1_data) - 8;
10450             else
10451               size = len - 8;
10452
10453             if (size < 1)
10454               /* No real data, so break out */
10455               break;
10456
10457             switch (QT_FOURCC (vc1_data + 0x4)) {
10458               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10459               {
10460                 GstBuffer *buf;
10461
10462                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10463                 buf = gst_buffer_new_and_alloc (size);
10464                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
10465                 gst_caps_set_simple (stream->caps,
10466                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10467                 gst_buffer_unref (buf);
10468                 break;
10469               }
10470               default:
10471                 break;
10472             }
10473             len -= size + 8;
10474             vc1_data += size + 8;
10475           }
10476           break;
10477         }
10478         default:
10479           break;
10480       }
10481     }
10482
10483     GST_INFO_OBJECT (qtdemux,
10484         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10485         GST_FOURCC_ARGS (fourcc), stream->caps);
10486
10487   } else if (stream->subtype == FOURCC_soun) {
10488     int version, samplesize;
10489     guint16 compression_id;
10490     gboolean amrwb = FALSE;
10491
10492     offset = 32;
10493     /* sample description entry (16) + sound sample description v0 (20) */
10494     if (len < 36)
10495       goto corrupt_file;
10496
10497     version = QT_UINT32 (stsd_data + offset);
10498     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
10499     samplesize = QT_UINT16 (stsd_data + offset + 10);
10500     compression_id = QT_UINT16 (stsd_data + offset + 12);
10501     stream->rate = QT_FP32 (stsd_data + offset + 16);
10502
10503     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10504     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10505         QT_UINT32 (stsd_data + offset + 4));
10506     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
10507     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10508     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10509     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10510         QT_UINT16 (stsd_data + offset + 14));
10511     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
10512
10513     if (compression_id == 0xfffe)
10514       stream->sampled = TRUE;
10515
10516     /* first assume uncompressed audio */
10517     stream->bytes_per_sample = samplesize / 8;
10518     stream->samples_per_frame = stream->n_channels;
10519     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
10520     stream->samples_per_packet = stream->samples_per_frame;
10521     stream->bytes_per_packet = stream->bytes_per_sample;
10522
10523     offset = 52;
10524     switch (fourcc) {
10525         /* Yes, these have to be hard-coded */
10526       case FOURCC_MAC6:
10527       {
10528         stream->samples_per_packet = 6;
10529         stream->bytes_per_packet = 1;
10530         stream->bytes_per_frame = 1 * stream->n_channels;
10531         stream->bytes_per_sample = 1;
10532         stream->samples_per_frame = 6 * stream->n_channels;
10533         break;
10534       }
10535       case FOURCC_MAC3:
10536       {
10537         stream->samples_per_packet = 3;
10538         stream->bytes_per_packet = 1;
10539         stream->bytes_per_frame = 1 * stream->n_channels;
10540         stream->bytes_per_sample = 1;
10541         stream->samples_per_frame = 3 * stream->n_channels;
10542         break;
10543       }
10544       case FOURCC_ima4:
10545       {
10546         stream->samples_per_packet = 64;
10547         stream->bytes_per_packet = 34;
10548         stream->bytes_per_frame = 34 * stream->n_channels;
10549         stream->bytes_per_sample = 2;
10550         stream->samples_per_frame = 64 * stream->n_channels;
10551         break;
10552       }
10553       case FOURCC_ulaw:
10554       case FOURCC_alaw:
10555       {
10556         stream->samples_per_packet = 1;
10557         stream->bytes_per_packet = 1;
10558         stream->bytes_per_frame = 1 * stream->n_channels;
10559         stream->bytes_per_sample = 1;
10560         stream->samples_per_frame = 1 * stream->n_channels;
10561         break;
10562       }
10563       case FOURCC_agsm:
10564       {
10565         stream->samples_per_packet = 160;
10566         stream->bytes_per_packet = 33;
10567         stream->bytes_per_frame = 33 * stream->n_channels;
10568         stream->bytes_per_sample = 2;
10569         stream->samples_per_frame = 160 * stream->n_channels;
10570         break;
10571       }
10572       default:
10573         break;
10574     }
10575
10576     if (version == 0x00010000) {
10577       /* sample description entry (16) + sound sample description v1 (20+16) */
10578       if (len < 52)
10579         goto corrupt_file;
10580
10581       switch (fourcc) {
10582         case FOURCC_twos:
10583         case FOURCC_sowt:
10584         case FOURCC_raw_:
10585           break;
10586         default:
10587         {
10588           /* only parse extra decoding config for non-pcm audio */
10589           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
10590           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
10591           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
10592           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
10593
10594           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10595               stream->samples_per_packet);
10596           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10597               stream->bytes_per_packet);
10598           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10599               stream->bytes_per_frame);
10600           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10601               stream->bytes_per_sample);
10602
10603           if (!stream->sampled && stream->bytes_per_packet) {
10604             stream->samples_per_frame = (stream->bytes_per_frame /
10605                 stream->bytes_per_packet) * stream->samples_per_packet;
10606             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10607                 stream->samples_per_frame);
10608           }
10609           break;
10610         }
10611       }
10612     } else if (version == 0x00020000) {
10613       union
10614       {
10615         gdouble fp;
10616         guint64 val;
10617       } qtfp;
10618
10619       /* sample description entry (16) + sound sample description v2 (56) */
10620       if (len < 72)
10621         goto corrupt_file;
10622
10623       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
10624       stream->rate = qtfp.fp;
10625       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
10626
10627       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10628       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
10629       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
10630       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10631           QT_UINT32 (stsd_data + offset + 20));
10632       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10633           QT_UINT32 (stsd_data + offset + 24));
10634       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10635           QT_UINT32 (stsd_data + offset + 28));
10636       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10637           QT_UINT32 (stsd_data + offset + 32));
10638     } else if (version != 0x00000) {
10639       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
10640     }
10641
10642     if (stream->caps)
10643       gst_caps_unref (stream->caps);
10644
10645     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
10646         stsd_data + 32, len - 16, &codec);
10647
10648     switch (fourcc) {
10649       case FOURCC_in24:
10650       {
10651         GNode *enda;
10652         GNode *in24;
10653
10654         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10655
10656         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10657         if (!enda) {
10658           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10659           if (wave)
10660             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10661         }
10662         if (enda) {
10663           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10664           gst_caps_set_simple (stream->caps,
10665               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
10666         }
10667         break;
10668       }
10669       case FOURCC_owma:
10670       {
10671         GNode *owma;
10672         const guint8 *owma_data;
10673         const gchar *codec_name = NULL;
10674         guint owma_len;
10675         GstBuffer *buf;
10676         gint version = 1;
10677         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10678         /* FIXME this should also be gst_riff_strf_auds,
10679          * but the latter one is actually missing bits-per-sample :( */
10680         typedef struct
10681         {
10682           gint16 wFormatTag;
10683           gint16 nChannels;
10684           gint32 nSamplesPerSec;
10685           gint32 nAvgBytesPerSec;
10686           gint16 nBlockAlign;
10687           gint16 wBitsPerSample;
10688           gint16 cbSize;
10689         } WAVEFORMATEX;
10690         WAVEFORMATEX *wfex;
10691
10692         GST_DEBUG_OBJECT (qtdemux, "parse owma");
10693         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
10694         if (!owma)
10695           break;
10696         owma_data = owma->data;
10697         owma_len = QT_UINT32 (owma_data);
10698         if (owma_len <= 54) {
10699           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10700           break;
10701         }
10702         wfex = (WAVEFORMATEX *) (owma_data + 36);
10703         buf = gst_buffer_new_and_alloc (owma_len - 54);
10704         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10705         if (wfex->wFormatTag == 0x0161) {
10706           codec_name = "Windows Media Audio";
10707           version = 2;
10708         } else if (wfex->wFormatTag == 0x0162) {
10709           codec_name = "Windows Media Audio 9 Pro";
10710           version = 3;
10711         } else if (wfex->wFormatTag == 0x0163) {
10712           codec_name = "Windows Media Audio 9 Lossless";
10713           /* is that correct? gstffmpegcodecmap.c is missing it, but
10714            * fluendo codec seems to support it */
10715           version = 4;
10716         }
10717
10718         gst_caps_set_simple (stream->caps,
10719             "codec_data", GST_TYPE_BUFFER, buf,
10720             "wmaversion", G_TYPE_INT, version,
10721             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
10722             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
10723             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10724             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
10725             NULL);
10726         gst_buffer_unref (buf);
10727
10728         if (codec_name) {
10729           g_free (codec);
10730           codec = g_strdup (codec_name);
10731         }
10732         break;
10733       }
10734       case FOURCC_wma_:
10735       {
10736         gint len = QT_UINT32 (stsd_data) - offset;
10737         const guint8 *wfex_data = stsd_data + offset;
10738         const gchar *codec_name = NULL;
10739         gint version = 1;
10740         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10741         /* FIXME this should also be gst_riff_strf_auds,
10742          * but the latter one is actually missing bits-per-sample :( */
10743         typedef struct
10744         {
10745           gint16 wFormatTag;
10746           gint16 nChannels;
10747           gint32 nSamplesPerSec;
10748           gint32 nAvgBytesPerSec;
10749           gint16 nBlockAlign;
10750           gint16 wBitsPerSample;
10751           gint16 cbSize;
10752         } WAVEFORMATEX;
10753         WAVEFORMATEX wfex;
10754
10755         /* FIXME: unify with similar wavformatex parsing code above */
10756         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10757
10758         /* find wfex */
10759         while (len >= 8) {
10760           gint size;
10761
10762           if (QT_UINT32 (wfex_data) <= len)
10763             size = QT_UINT32 (wfex_data) - 8;
10764           else
10765             size = len - 8;
10766
10767           if (size < 1)
10768             /* No real data, so break out */
10769             break;
10770
10771           switch (QT_FOURCC (wfex_data + 4)) {
10772             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10773             {
10774               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10775
10776               if (size < 8 + 18)
10777                 break;
10778
10779               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10780               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10781               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10782               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10783               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10784               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10785               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10786
10787               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10788               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10789                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10790                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10791                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
10792                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
10793
10794               if (wfex.wFormatTag == 0x0161) {
10795                 codec_name = "Windows Media Audio";
10796                 version = 2;
10797               } else if (wfex.wFormatTag == 0x0162) {
10798                 codec_name = "Windows Media Audio 9 Pro";
10799                 version = 3;
10800               } else if (wfex.wFormatTag == 0x0163) {
10801                 codec_name = "Windows Media Audio 9 Lossless";
10802                 /* is that correct? gstffmpegcodecmap.c is missing it, but
10803                  * fluendo codec seems to support it */
10804                 version = 4;
10805               }
10806
10807               gst_caps_set_simple (stream->caps,
10808                   "wmaversion", G_TYPE_INT, version,
10809                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
10810                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
10811                   "width", G_TYPE_INT, wfex.wBitsPerSample,
10812                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
10813
10814               if (size > wfex.cbSize) {
10815                 GstBuffer *buf;
10816
10817                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
10818                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
10819                     size - wfex.cbSize);
10820                 gst_caps_set_simple (stream->caps,
10821                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10822                 gst_buffer_unref (buf);
10823               } else {
10824                 GST_WARNING_OBJECT (qtdemux, "no codec data");
10825               }
10826
10827               if (codec_name) {
10828                 g_free (codec);
10829                 codec = g_strdup (codec_name);
10830               }
10831               break;
10832             }
10833             default:
10834               break;
10835           }
10836           len -= size + 8;
10837           wfex_data += size + 8;
10838         }
10839         break;
10840       }
10841       case FOURCC_opus:
10842       {
10843         GNode *opus;
10844         const guint8 *opus_data;
10845         guint8 *channel_mapping = NULL;
10846         guint32 rate;
10847         guint8 channels;
10848         guint8 channel_mapping_family;
10849         guint8 stream_count;
10850         guint8 coupled_count;
10851         guint8 i;
10852
10853         opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
10854         opus_data = opus->data;
10855
10856         channels = GST_READ_UINT8 (opus_data + 45);
10857         rate = GST_READ_UINT32_LE (opus_data + 48);
10858         channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
10859         stream_count = GST_READ_UINT8 (opus_data + 55);
10860         coupled_count = GST_READ_UINT8 (opus_data + 56);
10861
10862         if (channels > 0) {
10863           channel_mapping = g_malloc (channels * sizeof (guint8));
10864           for (i = 0; i < channels; i++)
10865             channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
10866         }
10867
10868         stream->caps = gst_codec_utils_opus_create_caps (rate, channels,
10869             channel_mapping_family, stream_count, coupled_count,
10870             channel_mapping);
10871         break;
10872       }
10873       default:
10874         break;
10875     }
10876
10877     if (codec) {
10878       GstStructure *s;
10879       gint bitrate = 0;
10880
10881       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10882           GST_TAG_AUDIO_CODEC, codec, NULL);
10883       g_free (codec);
10884       codec = NULL;
10885
10886       /* some bitrate info may have ended up in caps */
10887       s = gst_caps_get_structure (stream->caps, 0);
10888       gst_structure_get_int (s, "bitrate", &bitrate);
10889       if (bitrate > 0)
10890         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10891             GST_TAG_BITRATE, bitrate, NULL);
10892     }
10893
10894     if (stream->protected && fourcc == FOURCC_mp4a)
10895       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
10896     else
10897       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
10898
10899     wave = NULL;
10900     esds = NULL;
10901     if (mp4a) {
10902       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
10903       if (wave)
10904         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
10905       if (!esds)
10906         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
10907     }
10908
10909
10910     /* If the fourcc's bottom 16 bits gives 'sm', then the top
10911        16 bits is a byte-swapped wave-style codec identifier,
10912        and we can find a WAVE header internally to a 'wave' atom here.
10913        This can more clearly be thought of as 'ms' as the top 16 bits, and a
10914        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
10915        is big-endian).
10916      */
10917     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
10918       if (len < offset + 20) {
10919         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
10920       } else {
10921         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
10922         const guint8 *data = stsd_data + offset + 16;
10923         GNode *wavenode;
10924         GNode *waveheadernode;
10925
10926         wavenode = g_node_new ((guint8 *) data);
10927         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
10928           const guint8 *waveheader;
10929           guint32 headerlen;
10930
10931           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
10932           if (waveheadernode) {
10933             waveheader = (const guint8 *) waveheadernode->data;
10934             headerlen = QT_UINT32 (waveheader);
10935
10936             if (headerlen > 8) {
10937               gst_riff_strf_auds *header = NULL;
10938               GstBuffer *headerbuf;
10939               GstBuffer *extra;
10940
10941               waveheader += 8;
10942               headerlen -= 8;
10943
10944               headerbuf = gst_buffer_new_and_alloc (headerlen);
10945               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
10946
10947               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
10948                       headerbuf, &header, &extra)) {
10949                 gst_caps_unref (stream->caps);
10950                 /* FIXME: Need to do something with the channel reorder map */
10951                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
10952                     header, extra, NULL, NULL, NULL);
10953
10954                 if (extra)
10955                   gst_buffer_unref (extra);
10956                 g_free (header);
10957               }
10958             }
10959           } else
10960             GST_DEBUG ("Didn't find waveheadernode for this codec");
10961         }
10962         g_node_destroy (wavenode);
10963       }
10964     } else if (esds) {
10965       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10966     } else {
10967       switch (fourcc) {
10968 #if 0
10969           /* FIXME: what is in the chunk? */
10970         case FOURCC_QDMC:
10971         {
10972           gint len = QT_UINT32 (stsd_data);
10973
10974           /* seems to be always = 116 = 0x74 */
10975           break;
10976         }
10977 #endif
10978         case FOURCC_QDM2:
10979         {
10980           gint len = QT_UINT32 (stsd_data);
10981
10982           if (len > 0x4C) {
10983             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
10984
10985             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
10986             gst_caps_set_simple (stream->caps,
10987                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10988             gst_buffer_unref (buf);
10989           }
10990           gst_caps_set_simple (stream->caps,
10991               "samplesize", G_TYPE_INT, samplesize, NULL);
10992           break;
10993         }
10994         case FOURCC_alac:
10995         {
10996           GNode *alac, *wave = NULL;
10997
10998           /* apparently, m4a has this atom appended directly in the stsd entry,
10999            * while mov has it in a wave atom */
11000           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11001           if (alac) {
11002             /* alac now refers to stsd entry atom */
11003             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11004             if (wave)
11005               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11006             else
11007               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11008           }
11009           if (alac) {
11010             const guint8 *alac_data = alac->data;
11011             gint len = QT_UINT32 (alac->data);
11012             GstBuffer *buf;
11013
11014             if (len < 36) {
11015               GST_DEBUG_OBJECT (qtdemux,
11016                   "discarding alac atom with unexpected len %d", len);
11017             } else {
11018               /* codec-data contains alac atom size and prefix,
11019                * ffmpeg likes it that way, not quite gst-ish though ...*/
11020               buf = gst_buffer_new_and_alloc (len);
11021               gst_buffer_fill (buf, 0, alac->data, len);
11022               gst_caps_set_simple (stream->caps,
11023                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11024               gst_buffer_unref (buf);
11025
11026               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
11027               stream->n_channels = QT_UINT8 (alac_data + 21);
11028               stream->rate = QT_UINT32 (alac_data + 32);
11029             }
11030           }
11031           gst_caps_set_simple (stream->caps,
11032               "samplesize", G_TYPE_INT, samplesize, NULL);
11033           break;
11034         }
11035         case FOURCC_fLaC:
11036         {
11037           /* The codingname of the sample entry is 'fLaC' */
11038           GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11039
11040           if (flac) {
11041             /* The 'dfLa' box is added to the sample entry to convey
11042                initializing information for the decoder. */
11043             const GNode *dfla =
11044                 qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11045
11046             if (dfla) {
11047               const guint32 len = QT_UINT32 (dfla->data);
11048
11049               /* Must contain at least dfLa box header (12),
11050                * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11051               if (len < 50) {
11052                 GST_DEBUG_OBJECT (qtdemux,
11053                     "discarding dfla atom with unexpected len %d", len);
11054               } else {
11055                 /* skip dfLa header to get the METADATA_BLOCKs */
11056                 const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11057                 const guint32 metadata_blocks_len = len - 12;
11058
11059                 gchar *stream_marker = g_strdup ("fLaC");
11060                 GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11061                     strlen (stream_marker));
11062
11063                 guint32 index = 0;
11064                 guint32 remainder = 0;
11065                 guint32 block_size = 0;
11066                 gboolean is_last = FALSE;
11067
11068                 GValue array = G_VALUE_INIT;
11069                 GValue value = G_VALUE_INIT;
11070
11071                 g_value_init (&array, GST_TYPE_ARRAY);
11072                 g_value_init (&value, GST_TYPE_BUFFER);
11073
11074                 gst_value_set_buffer (&value, block);
11075                 gst_value_array_append_value (&array, &value);
11076                 g_value_reset (&value);
11077
11078                 gst_buffer_unref (block);
11079
11080                 /* check there's at least one METADATA_BLOCK_HEADER's worth
11081                  * of data, and we haven't already finished parsing */
11082                 while (!is_last && ((index + 3) < metadata_blocks_len)) {
11083                   remainder = metadata_blocks_len - index;
11084
11085                   /* add the METADATA_BLOCK_HEADER size to the signalled size */
11086                   block_size = 4 +
11087                       (metadata_blocks[index + 1] << 16) +
11088                       (metadata_blocks[index + 2] << 8) +
11089                       metadata_blocks[index + 3];
11090
11091                   /* be careful not to read off end of box */
11092                   if (block_size > remainder) {
11093                     break;
11094                   }
11095
11096                   is_last = metadata_blocks[index] >> 7;
11097
11098                   block = gst_buffer_new_and_alloc (block_size);
11099
11100                   gst_buffer_fill (block, 0, &metadata_blocks[index],
11101                       block_size);
11102
11103                   gst_value_set_buffer (&value, block);
11104                   gst_value_array_append_value (&array, &value);
11105                   g_value_reset (&value);
11106
11107                   gst_buffer_unref (block);
11108
11109                   index += block_size;
11110                 }
11111
11112                 /* only append the metadata if we successfully read all of it */
11113                 if (is_last) {
11114                   gst_structure_set_value (gst_caps_get_structure (stream->caps,
11115                           0), "streamheader", &array);
11116                 } else {
11117                   GST_WARNING_OBJECT (qtdemux,
11118                       "discarding all METADATA_BLOCKs due to invalid "
11119                       "block_size %d at idx %d, rem %d", block_size, index,
11120                       remainder);
11121                 }
11122
11123                 g_value_unset (&value);
11124                 g_value_unset (&array);
11125
11126                 /* The sample rate obtained from the stsd may not be accurate
11127                  * since it cannot represent rates greater than 65535Hz, so
11128                  * override that value with the sample rate from the
11129                  * METADATA_BLOCK_STREAMINFO block */
11130                 stream->rate =
11131                     (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11132               }
11133             }
11134           }
11135           break;
11136         }
11137         case FOURCC_sawb:
11138           /* Fallthrough! */
11139           amrwb = TRUE;
11140         case FOURCC_samr:
11141         {
11142           gint len = QT_UINT32 (stsd_data);
11143
11144           if (len > 0x34) {
11145             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
11146             guint bitrate;
11147
11148             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
11149
11150             /* If we have enough data, let's try to get the 'damr' atom. See
11151              * the 3GPP container spec (26.244) for more details. */
11152             if ((len - 0x34) > 8 &&
11153                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11154               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11155                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11156             }
11157
11158             gst_caps_set_simple (stream->caps,
11159                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11160             gst_buffer_unref (buf);
11161           }
11162           break;
11163         }
11164         case FOURCC_mp4a:
11165         {
11166           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11167           gint len = QT_UINT32 (stsd_data);
11168
11169           if (len >= 50) {
11170             guint16 sound_version = QT_UINT16 (stsd_data + 32);
11171
11172             if (sound_version == 1) {
11173               guint16 channels = QT_UINT16 (stsd_data + 40);
11174               guint32 time_scale = QT_UINT32 (stsd_data + 46);
11175               guint8 codec_data[2];
11176               GstBuffer *buf;
11177               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11178
11179               gint sample_rate_index =
11180                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11181
11182               /* build AAC codec data */
11183               codec_data[0] = profile << 3;
11184               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11185               codec_data[1] = (sample_rate_index & 0x01) << 7;
11186               codec_data[1] |= (channels & 0xF) << 3;
11187
11188               buf = gst_buffer_new_and_alloc (2);
11189               gst_buffer_fill (buf, 0, codec_data, 2);
11190               gst_caps_set_simple (stream->caps,
11191                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11192               gst_buffer_unref (buf);
11193             }
11194           }
11195           break;
11196         }
11197         default:
11198           GST_INFO_OBJECT (qtdemux,
11199               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11200           break;
11201       }
11202     }
11203     GST_INFO_OBJECT (qtdemux,
11204         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11205         GST_FOURCC_ARGS (fourcc), stream->caps);
11206
11207   } else if (stream->subtype == FOURCC_strm) {
11208     if (fourcc == FOURCC_rtsp) {
11209       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11210     } else {
11211       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11212           GST_FOURCC_ARGS (fourcc));
11213       goto unknown_stream;
11214     }
11215     stream->sampled = TRUE;
11216   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11217       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11218
11219     stream->sampled = TRUE;
11220     stream->sparse = TRUE;
11221
11222     stream->caps =
11223         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11224     if (codec) {
11225       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11226           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11227       g_free (codec);
11228       codec = NULL;
11229     }
11230
11231     /* hunt for sort-of codec data */
11232     switch (fourcc) {
11233       case FOURCC_mp4s:
11234       {
11235         GNode *mp4s = NULL;
11236         GNode *esds = NULL;
11237
11238         /* look for palette in a stsd->mp4s->esds sub-atom */
11239         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11240         if (mp4s)
11241           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11242         if (esds == NULL) {
11243           /* Invalid STSD */
11244           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11245           break;
11246         }
11247
11248         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
11249         break;
11250       }
11251       default:
11252         GST_INFO_OBJECT (qtdemux,
11253             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11254         break;
11255     }
11256     GST_INFO_OBJECT (qtdemux,
11257         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11258         GST_FOURCC_ARGS (fourcc), stream->caps);
11259   } else {
11260     /* everything in 1 sample */
11261     stream->sampled = TRUE;
11262
11263     stream->caps =
11264         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
11265
11266     if (stream->caps == NULL)
11267       goto unknown_stream;
11268
11269     if (codec) {
11270       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11271           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11272       g_free (codec);
11273       codec = NULL;
11274     }
11275   }
11276
11277   /* promote to sampled format */
11278   if (stream->fourcc == FOURCC_samr) {
11279     /* force mono 8000 Hz for AMR */
11280     stream->sampled = TRUE;
11281     stream->n_channels = 1;
11282     stream->rate = 8000;
11283   } else if (stream->fourcc == FOURCC_sawb) {
11284     /* force mono 16000 Hz for AMR-WB */
11285     stream->sampled = TRUE;
11286     stream->n_channels = 1;
11287     stream->rate = 16000;
11288   } else if (stream->fourcc == FOURCC_mp4a) {
11289     stream->sampled = TRUE;
11290   }
11291
11292   /* collect sample information */
11293   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11294     goto samples_failed;
11295
11296   if (qtdemux->fragmented) {
11297     guint64 offset;
11298
11299     /* need all moov samples as basis; probably not many if any at all */
11300     /* prevent moof parsing taking of at this time */
11301     offset = qtdemux->moof_offset;
11302     qtdemux->moof_offset = 0;
11303     if (stream->n_samples &&
11304         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11305       qtdemux->moof_offset = offset;
11306       goto samples_failed;
11307     }
11308     qtdemux->moof_offset = 0;
11309     /* movie duration more reliable in this case (e.g. mehd) */
11310     if (qtdemux->segment.duration &&
11311         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11312       stream->duration =
11313           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11314   }
11315
11316   /* configure segments */
11317   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11318     goto segments_failed;
11319
11320   /* add some language tag, if useful */
11321   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11322       strcmp (stream->lang_id, "und")) {
11323     const gchar *lang_code;
11324
11325     /* convert ISO 639-2 code to ISO 639-1 */
11326     lang_code = gst_tag_get_language_code (stream->lang_id);
11327     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11328         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11329   }
11330
11331   /* Check for UDTA tags */
11332   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11333     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
11334   }
11335
11336   /* now we are ready to add the stream */
11337   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11338     goto too_many_streams;
11339
11340   if (!qtdemux->got_moov) {
11341     qtdemux->streams[qtdemux->n_streams] = stream;
11342     qtdemux->n_streams++;
11343     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11344   }
11345
11346   return TRUE;
11347
11348 /* ERRORS */
11349 skip_track:
11350   {
11351     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11352     if (new_stream)
11353       gst_qtdemux_stream_free (qtdemux, stream);
11354     return TRUE;
11355   }
11356 corrupt_file:
11357   {
11358     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11359         (_("This file is corrupt and cannot be played.")), (NULL));
11360     if (new_stream)
11361       gst_qtdemux_stream_free (qtdemux, stream);
11362     return FALSE;
11363   }
11364 error_encrypted:
11365   {
11366     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11367     if (new_stream)
11368       gst_qtdemux_stream_free (qtdemux, stream);
11369     return FALSE;
11370   }
11371 samples_failed:
11372 segments_failed:
11373   {
11374     /* we posted an error already */
11375     /* free stbl sub-atoms */
11376     gst_qtdemux_stbl_free (stream);
11377     if (new_stream)
11378       gst_qtdemux_stream_free (qtdemux, stream);
11379     return FALSE;
11380   }
11381 existing_stream:
11382   {
11383     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11384         track_id);
11385     if (new_stream)
11386       gst_qtdemux_stream_free (qtdemux, stream);
11387     return TRUE;
11388   }
11389 unknown_stream:
11390   {
11391     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11392         GST_FOURCC_ARGS (stream->subtype));
11393     if (new_stream)
11394       gst_qtdemux_stream_free (qtdemux, stream);
11395     return TRUE;
11396   }
11397 too_many_streams:
11398   {
11399     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11400         (_("This file contains too many streams. Only playing first %d"),
11401             GST_QTDEMUX_MAX_STREAMS), (NULL));
11402     return TRUE;
11403   }
11404 }
11405
11406 /* If we can estimate the overall bitrate, and don't have information about the
11407  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11408  * the overall bitrate minus the sum of the bitrates of all other streams. This
11409  * should be useful for the common case where we have one audio and one video
11410  * stream and can estimate the bitrate of one, but not the other. */
11411 static void
11412 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11413 {
11414   QtDemuxStream *stream = NULL;
11415   gint64 size, sys_bitrate, sum_bitrate = 0;
11416   GstClockTime duration;
11417   gint i;
11418   guint bitrate;
11419
11420   if (qtdemux->fragmented)
11421     return;
11422
11423   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11424
11425   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11426       || size <= 0) {
11427     GST_DEBUG_OBJECT (qtdemux,
11428         "Size in bytes of the stream not known - bailing");
11429     return;
11430   }
11431
11432   /* Subtract the header size */
11433   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11434       size, qtdemux->header_size);
11435
11436   if (size < qtdemux->header_size)
11437     return;
11438
11439   size = size - qtdemux->header_size;
11440
11441   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11442     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11443     return;
11444   }
11445
11446   for (i = 0; i < qtdemux->n_streams; i++) {
11447     switch (qtdemux->streams[i]->subtype) {
11448       case FOURCC_soun:
11449       case FOURCC_vide:
11450         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11451             qtdemux->streams[i]->caps);
11452         /* retrieve bitrate, prefer avg then max */
11453         bitrate = 0;
11454         if (qtdemux->streams[i]->pending_tags) {
11455           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11456               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11457           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11458           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11459               GST_TAG_NOMINAL_BITRATE, &bitrate);
11460           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11461           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
11462               GST_TAG_BITRATE, &bitrate);
11463           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11464         }
11465         if (bitrate)
11466           sum_bitrate += bitrate;
11467         else {
11468           if (stream) {
11469             GST_DEBUG_OBJECT (qtdemux,
11470                 ">1 stream with unknown bitrate - bailing");
11471             return;
11472           } else
11473             stream = qtdemux->streams[i];
11474         }
11475
11476       default:
11477         /* For other subtypes, we assume no significant impact on bitrate */
11478         break;
11479     }
11480   }
11481
11482   if (!stream) {
11483     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11484     return;
11485   }
11486
11487   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11488
11489   if (sys_bitrate < sum_bitrate) {
11490     /* This can happen, since sum_bitrate might be derived from maximum
11491      * bitrates and not average bitrates */
11492     GST_DEBUG_OBJECT (qtdemux,
11493         "System bitrate less than sum bitrate - bailing");
11494     return;
11495   }
11496
11497   bitrate = sys_bitrate - sum_bitrate;
11498   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11499       ", Stream bitrate = %u", sys_bitrate, bitrate);
11500
11501   if (!stream->pending_tags)
11502     stream->pending_tags = gst_tag_list_new_empty ();
11503
11504   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
11505       GST_TAG_BITRATE, bitrate, NULL);
11506 }
11507
11508 static GstFlowReturn
11509 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11510 {
11511   gint i;
11512   GstFlowReturn ret = GST_FLOW_OK;
11513
11514   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11515
11516   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11517     QtDemuxStream *stream = qtdemux->streams[i];
11518     guint32 sample_num = 0;
11519
11520     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11521         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11522
11523     if (qtdemux->fragmented) {
11524       /* need all moov samples first */
11525       GST_OBJECT_LOCK (qtdemux);
11526       while (stream->n_samples == 0)
11527         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11528           break;
11529       GST_OBJECT_UNLOCK (qtdemux);
11530     } else {
11531       /* discard any stray moof */
11532       qtdemux->moof_offset = 0;
11533     }
11534
11535     /* prepare braking */
11536     if (ret != GST_FLOW_ERROR)
11537       ret = GST_FLOW_OK;
11538
11539     /* in pull mode, we should have parsed some sample info by now;
11540      * and quite some code will not handle no samples.
11541      * in push mode, we'll just have to deal with it */
11542     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11543       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11544       gst_qtdemux_remove_stream (qtdemux, i);
11545       i--;
11546       continue;
11547     }
11548
11549     /* parse the initial sample for use in setting the frame rate cap */
11550     while (sample_num == 0 && sample_num < stream->n_samples) {
11551       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11552         break;
11553       ++sample_num;
11554     }
11555     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11556       stream->first_duration = stream->samples[0].duration;
11557       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11558           stream->track_id, stream->first_duration);
11559     }
11560   }
11561
11562   return ret;
11563 }
11564
11565 static GstFlowReturn
11566 qtdemux_expose_streams (GstQTDemux * qtdemux)
11567 {
11568   gint i;
11569   GSList *oldpads = NULL;
11570   GSList *iter;
11571
11572   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11573
11574   for (i = 0; i < qtdemux->n_streams; i++) {
11575     QtDemuxStream *stream = qtdemux->streams[i];
11576     GstPad *oldpad = stream->pad;
11577     GstTagList *list;
11578
11579     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11580         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
11581
11582     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11583         stream->track_id == qtdemux->chapters_track_id) {
11584       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11585          so that it doesn't look like a subtitle track */
11586       gst_qtdemux_remove_stream (qtdemux, i);
11587       i--;
11588       continue;
11589     }
11590
11591     /* now we have all info and can expose */
11592     list = stream->pending_tags;
11593     stream->pending_tags = NULL;
11594     if (oldpad)
11595       oldpads = g_slist_prepend (oldpads, oldpad);
11596     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11597       return GST_FLOW_ERROR;
11598   }
11599
11600   gst_qtdemux_guess_bitrate (qtdemux);
11601
11602   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11603
11604   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11605     GstPad *oldpad = iter->data;
11606     GstEvent *event;
11607
11608     event = gst_event_new_eos ();
11609     if (qtdemux->segment_seqnum)
11610       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11611
11612     gst_pad_push_event (oldpad, event);
11613     gst_pad_set_active (oldpad, FALSE);
11614     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11615     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11616     gst_object_unref (oldpad);
11617   }
11618
11619   /* check if we should post a redirect in case there is a single trak
11620    * and it is a redirecting trak */
11621   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11622     GstMessage *m;
11623
11624     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11625         "an external content");
11626     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11627         gst_structure_new ("redirect",
11628             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11629             NULL));
11630     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11631     qtdemux->posted_redirect = TRUE;
11632   }
11633
11634   for (i = 0; i < qtdemux->n_streams; i++) {
11635     QtDemuxStream *stream = qtdemux->streams[i];
11636
11637     qtdemux_do_allocation (qtdemux, stream);
11638   }
11639
11640   qtdemux->exposed = TRUE;
11641   return GST_FLOW_OK;
11642 }
11643
11644 /* check if major or compatible brand is 3GP */
11645 static inline gboolean
11646 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11647 {
11648   if (major) {
11649     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11650         FOURCC_3g__);
11651   } else if (qtdemux->comp_brands != NULL) {
11652     GstMapInfo map;
11653     guint8 *data;
11654     gsize size;
11655     gboolean res = FALSE;
11656
11657     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11658     data = map.data;
11659     size = map.size;
11660     while (size >= 4) {
11661       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11662           FOURCC_3g__);
11663       data += 4;
11664       size -= 4;
11665     }
11666     gst_buffer_unmap (qtdemux->comp_brands, &map);
11667     return res;
11668   } else {
11669     return FALSE;
11670   }
11671 }
11672
11673 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11674 static inline gboolean
11675 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11676 {
11677   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11678       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11679       || fourcc == FOURCC_albm;
11680 }
11681
11682 static void
11683 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11684     const char *tag, const char *dummy, GNode * node)
11685 {
11686   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11687   int offset;
11688   char *name;
11689   gchar *data;
11690   gdouble longitude, latitude, altitude;
11691   gint len;
11692
11693   len = QT_UINT32 (node->data);
11694   if (len <= 14)
11695     goto short_read;
11696
11697   data = node->data;
11698   offset = 14;
11699
11700   /* TODO: language code skipped */
11701
11702   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11703
11704   if (!name) {
11705     /* do not alarm in trivial case, but bail out otherwise */
11706     if (*(data + offset) != 0) {
11707       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11708           "giving up", tag);
11709     }
11710   } else {
11711     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11712         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11713     offset += strlen (name);
11714     g_free (name);
11715   }
11716
11717   if (len < offset + 2 + 4 + 4 + 4)
11718     goto short_read;
11719
11720   /* +1 +1 = skip null-terminator and location role byte */
11721   offset += 1 + 1;
11722   /* table in spec says unsigned, semantics say negative has meaning ... */
11723   longitude = QT_SFP32 (data + offset);
11724
11725   offset += 4;
11726   latitude = QT_SFP32 (data + offset);
11727
11728   offset += 4;
11729   altitude = QT_SFP32 (data + offset);
11730
11731   /* one invalid means all are invalid */
11732   if (longitude >= -180.0 && longitude <= 180.0 &&
11733       latitude >= -90.0 && latitude <= 90.0) {
11734     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11735         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11736         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11737         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11738   }
11739
11740   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11741
11742   return;
11743
11744   /* ERRORS */
11745 short_read:
11746   {
11747     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11748     return;
11749   }
11750 }
11751
11752
11753 static void
11754 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11755     const char *tag, const char *dummy, GNode * node)
11756 {
11757   guint16 y;
11758   GDate *date;
11759   gint len;
11760
11761   len = QT_UINT32 (node->data);
11762   if (len < 14)
11763     return;
11764
11765   y = QT_UINT16 ((guint8 *) node->data + 12);
11766   if (y == 0) {
11767     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11768     return;
11769   }
11770   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
11771
11772   date = g_date_new_dmy (1, 1, y);
11773   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
11774   g_date_free (date);
11775 }
11776
11777 static void
11778 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
11779     const char *tag, const char *dummy, GNode * node)
11780 {
11781   int offset;
11782   char *tag_str = NULL;
11783   guint8 *entity;
11784   guint16 table;
11785   gint len;
11786
11787   len = QT_UINT32 (node->data);
11788   if (len <= 20)
11789     goto short_read;
11790
11791   offset = 12;
11792   entity = (guint8 *) node->data + offset;
11793   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
11794     GST_DEBUG_OBJECT (qtdemux,
11795         "classification info: %c%c%c%c invalid classification entity",
11796         entity[0], entity[1], entity[2], entity[3]);
11797     return;
11798   }
11799
11800   offset += 4;
11801   table = QT_UINT16 ((guint8 *) node->data + offset);
11802
11803   /* Language code skipped */
11804
11805   offset += 4;
11806
11807   /* Tag format: "XXXX://Y[YYYY]/classification info string"
11808    * XXXX: classification entity, fixed length 4 chars.
11809    * Y[YYYY]: classification table, max 5 chars.
11810    */
11811   tag_str = g_strdup_printf ("----://%u/%s",
11812       table, (char *) node->data + offset);
11813
11814   /* memcpy To be sure we're preserving byte order */
11815   memcpy (tag_str, entity, 4);
11816   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
11817
11818   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
11819
11820   g_free (tag_str);
11821
11822   return;
11823
11824   /* ERRORS */
11825 short_read:
11826   {
11827     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
11828     return;
11829   }
11830 }
11831
11832 static gboolean
11833 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
11834     const char *tag, const char *dummy, GNode * node)
11835 {
11836   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11837   GNode *data;
11838   char *s;
11839   int len;
11840   guint32 type;
11841   int offset;
11842   gboolean ret = TRUE;
11843   const gchar *charset = NULL;
11844
11845   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11846   if (data) {
11847     len = QT_UINT32 (data->data);
11848     type = QT_UINT32 ((guint8 *) data->data + 8);
11849     if (type == 0x00000001 && len > 16) {
11850       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
11851           env_vars);
11852       if (s) {
11853         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11854         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11855         g_free (s);
11856       } else {
11857         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11858       }
11859     }
11860   } else {
11861     len = QT_UINT32 (node->data);
11862     type = QT_UINT32 ((guint8 *) node->data + 4);
11863     if ((type >> 24) == 0xa9 && len > 8 + 4) {
11864       gint str_len;
11865       gint lang_code;
11866
11867       /* Type starts with the (C) symbol, so the next data is a list
11868        * of (string size(16), language code(16), string) */
11869
11870       str_len = QT_UINT16 ((guint8 *) node->data + 8);
11871       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
11872
11873       /* the string + fourcc + size + 2 16bit fields,
11874        * means that there are more tags in this atom */
11875       if (len > str_len + 8 + 4) {
11876         /* TODO how to represent the same tag in different languages? */
11877         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
11878             "text alternatives, reading only first one");
11879       }
11880
11881       offset = 12;
11882       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
11883       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
11884
11885       if (lang_code < 0x800) {  /* MAC encoded string */
11886         charset = "mac";
11887       }
11888     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
11889             QT_FOURCC ((guint8 *) node->data + 4))) {
11890       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
11891
11892       /* we go for 3GP style encoding if major brands claims so,
11893        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
11894       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
11895           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
11896               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
11897         offset = 14;
11898         /* 16-bit Language code is ignored here as well */
11899         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
11900       } else {
11901         goto normal;
11902       }
11903     } else {
11904     normal:
11905       offset = 8;
11906       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
11907       ret = FALSE;              /* may have to fallback */
11908     }
11909     if (charset) {
11910       GError *err = NULL;
11911
11912       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
11913           charset, NULL, NULL, &err);
11914       if (err) {
11915         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
11916             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
11917             err->message);
11918         g_error_free (err);
11919       }
11920     } else {
11921       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11922           len - offset, env_vars);
11923     }
11924     if (s) {
11925       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
11926       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
11927       g_free (s);
11928       ret = TRUE;
11929     } else {
11930       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
11931     }
11932   }
11933   return ret;
11934 }
11935
11936 static void
11937 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
11938     const char *tag, const char *dummy, GNode * node)
11939 {
11940   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
11941 }
11942
11943 static void
11944 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
11945     const char *tag, const char *dummy, GNode * node)
11946 {
11947   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11948   guint8 *data;
11949   char *s, *t, *k = NULL;
11950   int len;
11951   int offset;
11952   int count;
11953
11954   /* first try normal string tag if major brand not 3GP */
11955   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
11956     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
11957       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
11958        * let's try it 3gpp way after minor safety check */
11959       data = node->data;
11960       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
11961         return;
11962     } else
11963       return;
11964   }
11965
11966   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
11967
11968   data = node->data;
11969
11970   len = QT_UINT32 (data);
11971   if (len < 15)
11972     goto short_read;
11973
11974   count = QT_UINT8 (data + 14);
11975   offset = 15;
11976   for (; count; count--) {
11977     gint slen;
11978
11979     if (offset + 1 > len)
11980       goto short_read;
11981     slen = QT_UINT8 (data + offset);
11982     offset += 1;
11983     if (offset + slen > len)
11984       goto short_read;
11985     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
11986         slen, env_vars);
11987     if (s) {
11988       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
11989       if (k) {
11990         t = g_strjoin (",", k, s, NULL);
11991         g_free (s);
11992         g_free (k);
11993         k = t;
11994       } else {
11995         k = s;
11996       }
11997     } else {
11998       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
11999     }
12000     offset += slen;
12001   }
12002
12003 done:
12004   if (k) {
12005     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12006     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12007   }
12008   g_free (k);
12009
12010   return;
12011
12012   /* ERRORS */
12013 short_read:
12014   {
12015     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12016     goto done;
12017   }
12018 }
12019
12020 static void
12021 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12022     const char *tag1, const char *tag2, GNode * node)
12023 {
12024   GNode *data;
12025   int len;
12026   int type;
12027   int n1, n2;
12028
12029   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12030   if (data) {
12031     len = QT_UINT32 (data->data);
12032     type = QT_UINT32 ((guint8 *) data->data + 8);
12033     if (type == 0x00000000 && len >= 22) {
12034       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12035       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12036       if (n1 > 0) {
12037         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12038         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12039       }
12040       if (n2 > 0) {
12041         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12042         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12043       }
12044     }
12045   }
12046 }
12047
12048 static void
12049 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12050     const char *tag1, const char *dummy, GNode * node)
12051 {
12052   GNode *data;
12053   int len;
12054   int type;
12055   int n1;
12056
12057   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12058   if (data) {
12059     len = QT_UINT32 (data->data);
12060     type = QT_UINT32 ((guint8 *) data->data + 8);
12061     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12062     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12063     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12064       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12065       if (n1) {
12066         /* do not add bpm=0 */
12067         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12068         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12069             NULL);
12070       }
12071     }
12072   }
12073 }
12074
12075 static void
12076 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12077     const char *tag1, const char *dummy, GNode * node)
12078 {
12079   GNode *data;
12080   int len;
12081   int type;
12082   guint32 num;
12083
12084   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12085   if (data) {
12086     len = QT_UINT32 (data->data);
12087     type = QT_UINT32 ((guint8 *) data->data + 8);
12088     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12089     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12090     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12091       num = QT_UINT32 ((guint8 *) data->data + 16);
12092       if (num) {
12093         /* do not add num=0 */
12094         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12095         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12096       }
12097     }
12098   }
12099 }
12100
12101 static void
12102 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12103     const char *tag1, const char *dummy, GNode * node)
12104 {
12105   GNode *data;
12106   int len;
12107   int type;
12108   GstSample *sample;
12109
12110   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12111   if (data) {
12112     len = QT_UINT32 (data->data);
12113     type = QT_UINT32 ((guint8 *) data->data + 8);
12114     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12115     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12116       GstTagImageType image_type;
12117
12118       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12119         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12120       else
12121         image_type = GST_TAG_IMAGE_TYPE_NONE;
12122
12123       if ((sample =
12124               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12125                   len - 16, image_type))) {
12126         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12127         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12128         gst_sample_unref (sample);
12129       }
12130     }
12131   }
12132 }
12133
12134 static void
12135 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12136     const char *tag, const char *dummy, GNode * node)
12137 {
12138   GNode *data;
12139   char *s;
12140   int len;
12141   int type;
12142
12143   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12144   if (data) {
12145     len = QT_UINT32 (data->data);
12146     type = QT_UINT32 ((guint8 *) data->data + 8);
12147     if (type == 0x00000001 && len > 16) {
12148       guint y, m = 1, d = 1;
12149       gint ret;
12150
12151       s = g_strndup ((char *) data->data + 16, len - 16);
12152       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12153       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12154       if (ret >= 1 && y > 1500 && y < 3000) {
12155         GDate *date;
12156
12157         date = g_date_new_dmy (d, m, y);
12158         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12159         g_date_free (date);
12160       } else {
12161         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12162       }
12163       g_free (s);
12164     }
12165   }
12166 }
12167
12168 static void
12169 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12170     const char *tag, const char *dummy, GNode * node)
12171 {
12172   GNode *data;
12173
12174   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12175
12176   /* re-route to normal string tag if major brand says so
12177    * or no data atom and compatible brand suggests so */
12178   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12179       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12180     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12181     return;
12182   }
12183
12184   if (data) {
12185     guint len, type, n;
12186
12187     len = QT_UINT32 (data->data);
12188     type = QT_UINT32 ((guint8 *) data->data + 8);
12189     if (type == 0x00000000 && len >= 18) {
12190       n = QT_UINT16 ((guint8 *) data->data + 16);
12191       if (n > 0) {
12192         const gchar *genre;
12193
12194         genre = gst_tag_id3_genre_get (n - 1);
12195         if (genre != NULL) {
12196           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12197           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12198         }
12199       }
12200     }
12201   }
12202 }
12203
12204 static void
12205 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12206     const gchar * tag, guint8 * data, guint32 datasize)
12207 {
12208   gdouble value;
12209   gchar *datacopy;
12210
12211   /* make a copy to have \0 at the end */
12212   datacopy = g_strndup ((gchar *) data, datasize);
12213
12214   /* convert the str to double */
12215   if (sscanf (datacopy, "%lf", &value) == 1) {
12216     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12217     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12218   } else {
12219     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12220         datacopy);
12221   }
12222   g_free (datacopy);
12223 }
12224
12225
12226 static void
12227 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12228     const char *tag, const char *tag_bis, GNode * node)
12229 {
12230   GNode *mean;
12231   GNode *name;
12232   GNode *data;
12233   guint32 meansize;
12234   guint32 namesize;
12235   guint32 datatype;
12236   guint32 datasize;
12237   const gchar *meanstr;
12238   const gchar *namestr;
12239
12240   /* checking the whole ---- atom size for consistency */
12241   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12242     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12243     return;
12244   }
12245
12246   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12247   if (!mean) {
12248     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12249     return;
12250   }
12251
12252   meansize = QT_UINT32 (mean->data);
12253   if (meansize <= 12) {
12254     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12255     return;
12256   }
12257   meanstr = ((gchar *) mean->data) + 12;
12258   meansize -= 12;
12259
12260   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12261   if (!name) {
12262     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12263     return;
12264   }
12265
12266   namesize = QT_UINT32 (name->data);
12267   if (namesize <= 12) {
12268     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12269     return;
12270   }
12271   namestr = ((gchar *) name->data) + 12;
12272   namesize -= 12;
12273
12274   /*
12275    * Data atom is:
12276    * uint32 - size
12277    * uint32 - name
12278    * uint8  - version
12279    * uint24 - data type
12280    * uint32 - all 0
12281    * rest   - the data
12282    */
12283   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12284   if (!data) {
12285     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12286     return;
12287   }
12288   datasize = QT_UINT32 (data->data);
12289   if (datasize <= 16) {
12290     GST_WARNING_OBJECT (demux, "Data atom too small");
12291     return;
12292   }
12293   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12294
12295   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12296       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12297     static const struct
12298     {
12299       const gchar name[28];
12300       const gchar tag[28];
12301     } tags[] = {
12302       {
12303       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12304       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12305       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12306       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12307       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12308       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12309       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12310       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12311     };
12312     int i;
12313
12314     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12315       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12316         switch (gst_tag_get_type (tags[i].tag)) {
12317           case G_TYPE_DOUBLE:
12318             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12319                 ((guint8 *) data->data) + 16, datasize - 16);
12320             break;
12321           case G_TYPE_STRING:
12322             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12323             break;
12324           default:
12325             /* not reached */
12326             break;
12327         }
12328         break;
12329       }
12330     }
12331     if (i == G_N_ELEMENTS (tags))
12332       goto unknown_tag;
12333   } else {
12334     goto unknown_tag;
12335   }
12336
12337   return;
12338
12339 /* errors */
12340 unknown_tag:
12341 #ifndef GST_DISABLE_GST_DEBUG
12342   {
12343     gchar *namestr_dbg;
12344     gchar *meanstr_dbg;
12345
12346     meanstr_dbg = g_strndup (meanstr, meansize);
12347     namestr_dbg = g_strndup (namestr, namesize);
12348
12349     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12350         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12351
12352     g_free (namestr_dbg);
12353     g_free (meanstr_dbg);
12354   }
12355 #endif
12356   return;
12357 }
12358
12359 static void
12360 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12361     const char *tag_bis, GNode * node)
12362 {
12363   guint8 *data;
12364   GstBuffer *buf;
12365   guint len;
12366   GstTagList *id32_taglist = NULL;
12367
12368   GST_LOG_OBJECT (demux, "parsing ID32");
12369
12370   data = node->data;
12371   len = GST_READ_UINT32_BE (data);
12372
12373   /* need at least full box and language tag */
12374   if (len < 12 + 2)
12375     return;
12376
12377   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12378   gst_buffer_fill (buf, 0, data + 14, len - 14);
12379
12380   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12381   if (id32_taglist) {
12382     GST_LOG_OBJECT (demux, "parsing ok");
12383     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12384     gst_tag_list_unref (id32_taglist);
12385   } else {
12386     GST_LOG_OBJECT (demux, "parsing failed");
12387   }
12388
12389   gst_buffer_unref (buf);
12390 }
12391
12392 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12393     const char *tag, const char *tag_bis, GNode * node);
12394
12395 /* unmapped tags
12396 FOURCC_pcst -> if media is a podcast -> bool
12397 FOURCC_cpil -> if media is part of a compilation -> bool
12398 FOURCC_pgap -> if media is part of a gapless context -> bool
12399 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12400 */
12401
12402 static const struct
12403 {
12404   guint32 fourcc;
12405   const gchar *gst_tag;
12406   const gchar *gst_tag_bis;
12407   const GstQTDemuxAddTagFunc func;
12408 } add_funcs[] = {
12409   {
12410   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12411   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12412   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12413   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12414   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12415   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12416   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12417   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12418   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12419   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12420   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12421   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12422   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12423   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12424   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12425   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12426   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12427   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12428   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12429   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12430   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12431   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12432   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12433         qtdemux_tag_add_num}, {
12434   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12435         qtdemux_tag_add_num}, {
12436   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12437   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12438   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12439   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12440   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12441   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12442   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12443   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12444   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12445   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12446   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12447   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12448   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12449   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12450   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12451   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12452   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12453   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12454         qtdemux_tag_add_classification}, {
12455   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12456   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12457   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12458
12459     /* This is a special case, some tags are stored in this
12460      * 'reverse dns naming', according to:
12461      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12462      * bug #614471
12463      */
12464   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12465     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12466   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12467 };
12468
12469 struct _GstQtDemuxTagList
12470 {
12471   GstQTDemux *demux;
12472   GstTagList *taglist;
12473 };
12474 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12475
12476 static void
12477 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12478 {
12479   gint len;
12480   guint8 *data;
12481   GstBuffer *buf;
12482   gchar *media_type;
12483   const gchar *style;
12484   GstSample *sample;
12485   GstStructure *s;
12486   guint i;
12487   guint8 ndata[4];
12488   GstQTDemux *demux = qtdemuxtaglist->demux;
12489   GstTagList *taglist = qtdemuxtaglist->taglist;
12490
12491   data = node->data;
12492   len = QT_UINT32 (data);
12493   buf = gst_buffer_new_and_alloc (len);
12494   gst_buffer_fill (buf, 0, data, len);
12495
12496   /* heuristic to determine style of tag */
12497   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12498       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12499     style = "itunes";
12500   else if (demux->major_brand == FOURCC_qt__)
12501     style = "quicktime";
12502   /* fall back to assuming iso/3gp tag style */
12503   else
12504     style = "iso";
12505
12506   /* santize the name for the caps. */
12507   for (i = 0; i < 4; i++) {
12508     guint8 d = data[4 + i];
12509     if (g_ascii_isalnum (d))
12510       ndata[i] = g_ascii_tolower (d);
12511     else
12512       ndata[i] = '_';
12513   }
12514
12515   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12516       ndata[0], ndata[1], ndata[2], ndata[3]);
12517   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12518
12519   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12520   sample = gst_sample_new (buf, NULL, NULL, s);
12521   gst_buffer_unref (buf);
12522   g_free (media_type);
12523
12524   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12525       len, s);
12526
12527   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12528       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12529
12530   gst_sample_unref (sample);
12531 }
12532
12533 static void
12534 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12535 {
12536   GNode *meta;
12537   GNode *ilst;
12538   GNode *xmp_;
12539   GNode *node;
12540   gint i;
12541   GstQtDemuxTagList demuxtaglist;
12542
12543   demuxtaglist.demux = qtdemux;
12544   demuxtaglist.taglist = taglist;
12545
12546   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12547   if (meta != NULL) {
12548     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12549     if (ilst == NULL) {
12550       GST_LOG_OBJECT (qtdemux, "no ilst");
12551       return;
12552     }
12553   } else {
12554     ilst = udta;
12555     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12556   }
12557
12558   i = 0;
12559   while (i < G_N_ELEMENTS (add_funcs)) {
12560     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12561     if (node) {
12562       gint len;
12563
12564       len = QT_UINT32 (node->data);
12565       if (len < 12) {
12566         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12567             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12568       } else {
12569         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12570             add_funcs[i].gst_tag_bis, node);
12571       }
12572       g_node_destroy (node);
12573     } else {
12574       i++;
12575     }
12576   }
12577
12578   /* parsed nodes have been removed, pass along remainder as blob */
12579   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12580       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12581
12582   /* parse up XMP_ node if existing */
12583   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12584   if (xmp_ != NULL) {
12585     GstBuffer *buf;
12586     GstTagList *xmptaglist;
12587
12588     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12589         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12590     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12591     gst_buffer_unref (buf);
12592
12593     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12594   } else {
12595     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12596   }
12597 }
12598
12599 typedef struct
12600 {
12601   GstStructure *structure;      /* helper for sort function */
12602   gchar *location;
12603   guint min_req_bitrate;
12604   guint min_req_qt_version;
12605 } GstQtReference;
12606
12607 static gint
12608 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12609 {
12610   GstQtReference *ref_a = (GstQtReference *) a;
12611   GstQtReference *ref_b = (GstQtReference *) b;
12612
12613   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12614     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12615
12616   /* known bitrates go before unknown; higher bitrates go first */
12617   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12618 }
12619
12620 /* sort the redirects and post a message for the application.
12621  */
12622 static void
12623 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12624 {
12625   GstQtReference *best;
12626   GstStructure *s;
12627   GstMessage *msg;
12628   GValue list_val = { 0, };
12629   GList *l;
12630
12631   g_assert (references != NULL);
12632
12633   references = g_list_sort (references, qtdemux_redirects_sort_func);
12634
12635   best = (GstQtReference *) references->data;
12636
12637   g_value_init (&list_val, GST_TYPE_LIST);
12638
12639   for (l = references; l != NULL; l = l->next) {
12640     GstQtReference *ref = (GstQtReference *) l->data;
12641     GValue struct_val = { 0, };
12642
12643     ref->structure = gst_structure_new ("redirect",
12644         "new-location", G_TYPE_STRING, ref->location, NULL);
12645
12646     if (ref->min_req_bitrate > 0) {
12647       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12648           ref->min_req_bitrate, NULL);
12649     }
12650
12651     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12652     g_value_set_boxed (&struct_val, ref->structure);
12653     gst_value_list_append_value (&list_val, &struct_val);
12654     g_value_unset (&struct_val);
12655     /* don't free anything here yet, since we need best->structure below */
12656   }
12657
12658   g_assert (best != NULL);
12659   s = gst_structure_copy (best->structure);
12660
12661   if (g_list_length (references) > 1) {
12662     gst_structure_set_value (s, "locations", &list_val);
12663   }
12664
12665   g_value_unset (&list_val);
12666
12667   for (l = references; l != NULL; l = l->next) {
12668     GstQtReference *ref = (GstQtReference *) l->data;
12669
12670     gst_structure_free (ref->structure);
12671     g_free (ref->location);
12672     g_free (ref);
12673   }
12674   g_list_free (references);
12675
12676   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12677   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12678   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12679   qtdemux->posted_redirect = TRUE;
12680 }
12681
12682 /* look for redirect nodes, collect all redirect information and
12683  * process it.
12684  */
12685 static gboolean
12686 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12687 {
12688   GNode *rmra, *rmda, *rdrf;
12689
12690   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12691   if (rmra) {
12692     GList *redirects = NULL;
12693
12694     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12695     while (rmda) {
12696       GstQtReference ref = { NULL, NULL, 0, 0 };
12697       GNode *rmdr, *rmvc;
12698
12699       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12700         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12701         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12702             ref.min_req_bitrate);
12703       }
12704
12705       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12706         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12707         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12708
12709 #ifndef GST_DISABLE_GST_DEBUG
12710         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12711 #endif
12712         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12713
12714         GST_LOG_OBJECT (qtdemux,
12715             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12716             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12717             bitmask, check_type);
12718         if (package == FOURCC_qtim && check_type == 0) {
12719           ref.min_req_qt_version = version;
12720         }
12721       }
12722
12723       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12724       if (rdrf) {
12725         guint32 ref_type;
12726         guint8 *ref_data;
12727         guint ref_len;
12728
12729         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12730         if (ref_len > 20) {
12731           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12732           ref_data = (guint8 *) rdrf->data + 20;
12733           if (ref_type == FOURCC_alis) {
12734             guint record_len, record_version, fn_len;
12735
12736             if (ref_len > 70) {
12737               /* MacOSX alias record, google for alias-layout.txt */
12738               record_len = QT_UINT16 (ref_data + 4);
12739               record_version = QT_UINT16 (ref_data + 4 + 2);
12740               fn_len = QT_UINT8 (ref_data + 50);
12741               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12742                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12743               }
12744             } else {
12745               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12746                   ref_len);
12747             }
12748           } else if (ref_type == FOURCC_url_) {
12749             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12750           } else {
12751             GST_DEBUG_OBJECT (qtdemux,
12752                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12753                 GST_FOURCC_ARGS (ref_type));
12754           }
12755           if (ref.location != NULL) {
12756             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12757             redirects =
12758                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12759           } else {
12760             GST_WARNING_OBJECT (qtdemux,
12761                 "Failed to extract redirect location from rdrf atom");
12762           }
12763         } else {
12764           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12765         }
12766       }
12767
12768       /* look for others */
12769       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
12770     }
12771
12772     if (redirects != NULL) {
12773       qtdemux_process_redirects (qtdemux, redirects);
12774     }
12775   }
12776   return TRUE;
12777 }
12778
12779 static GstTagList *
12780 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
12781 {
12782   const gchar *fmt;
12783
12784   if (tags == NULL) {
12785     tags = gst_tag_list_new_empty ();
12786     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
12787   }
12788
12789   if (qtdemux->major_brand == FOURCC_mjp2)
12790     fmt = "Motion JPEG 2000";
12791   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
12792     fmt = "3GP";
12793   else if (qtdemux->major_brand == FOURCC_qt__)
12794     fmt = "Quicktime";
12795   else if (qtdemux->fragmented)
12796     fmt = "ISO fMP4";
12797   else
12798     fmt = "ISO MP4/M4A";
12799
12800   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
12801       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
12802
12803   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
12804       fmt, NULL);
12805
12806   return tags;
12807 }
12808
12809 /* we have read the complete moov node now.
12810  * This function parses all of the relevant info, creates the traks and
12811  * prepares all data structures for playback
12812  */
12813 static gboolean
12814 qtdemux_parse_tree (GstQTDemux * qtdemux)
12815 {
12816   GNode *mvhd;
12817   GNode *trak;
12818   GNode *udta;
12819   GNode *mvex;
12820   GstClockTime duration;
12821   GNode *pssh;
12822   guint64 creation_time;
12823   GstDateTime *datetime = NULL;
12824   gint version;
12825
12826   /* make sure we have a usable taglist */
12827   if (!qtdemux->tag_list) {
12828     qtdemux->tag_list = gst_tag_list_new_empty ();
12829     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12830   } else {
12831     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12832   }
12833
12834   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
12835   if (mvhd == NULL) {
12836     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
12837     return qtdemux_parse_redirects (qtdemux);
12838   }
12839
12840   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
12841   if (version == 1) {
12842     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
12843     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
12844     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
12845   } else if (version == 0) {
12846     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
12847     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
12848     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
12849   } else {
12850     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
12851     return FALSE;
12852   }
12853
12854   /* Moving qt creation time (secs since 1904) to unix time */
12855   if (creation_time != 0) {
12856     /* Try to use epoch first as it should be faster and more commonly found */
12857     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
12858       GTimeVal now;
12859
12860       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
12861       /* some data cleansing sanity */
12862       g_get_current_time (&now);
12863       if (now.tv_sec + 24 * 3600 < creation_time) {
12864         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
12865       } else {
12866         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
12867       }
12868     } else {
12869       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
12870       GDateTime *dt, *dt_local;
12871
12872       dt = g_date_time_add_seconds (base_dt, creation_time);
12873       dt_local = g_date_time_to_local (dt);
12874       datetime = gst_date_time_new_from_g_date_time (dt_local);
12875
12876       g_date_time_unref (base_dt);
12877       g_date_time_unref (dt);
12878     }
12879   }
12880   if (datetime) {
12881     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
12882     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
12883         datetime, NULL);
12884     gst_date_time_unref (datetime);
12885   }
12886
12887   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
12888   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
12889
12890   /* check for fragmented file and get some (default) data */
12891   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
12892   if (mvex) {
12893     GNode *mehd;
12894     GstByteReader mehd_data;
12895
12896     /* let track parsing or anyone know weird stuff might happen ... */
12897     qtdemux->fragmented = TRUE;
12898
12899     /* compensate for total duration */
12900     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
12901     if (mehd)
12902       qtdemux_parse_mehd (qtdemux, &mehd_data);
12903   }
12904
12905   /* set duration in the segment info */
12906   gst_qtdemux_get_duration (qtdemux, &duration);
12907   if (duration) {
12908     qtdemux->segment.duration = duration;
12909     /* also do not exceed duration; stop is set that way post seek anyway,
12910      * and segment activation falls back to duration,
12911      * whereas loop only checks stop, so let's align this here as well */
12912     qtdemux->segment.stop = duration;
12913   }
12914
12915   /* parse all traks */
12916   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
12917   while (trak) {
12918     qtdemux_parse_trak (qtdemux, trak);
12919     /* iterate all siblings */
12920     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
12921   }
12922
12923   if (!qtdemux->tag_list) {
12924     GST_DEBUG_OBJECT (qtdemux, "new tag list");
12925     qtdemux->tag_list = gst_tag_list_new_empty ();
12926     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
12927   } else {
12928     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
12929   }
12930
12931   /* find tags */
12932   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
12933   if (udta) {
12934     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12935   } else {
12936     GST_LOG_OBJECT (qtdemux, "No udta node found.");
12937   }
12938
12939   /* maybe also some tags in meta box */
12940   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
12941   if (udta) {
12942     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
12943     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
12944   } else {
12945     GST_LOG_OBJECT (qtdemux, "No meta node found.");
12946   }
12947
12948   /* parse any protection system info */
12949   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
12950   while (pssh) {
12951     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
12952     qtdemux_parse_pssh (qtdemux, pssh);
12953     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
12954   }
12955
12956   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
12957
12958   return TRUE;
12959 }
12960
12961 /* taken from ffmpeg */
12962 static int
12963 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
12964 {
12965   int count = 4;
12966   int len = 0;
12967
12968   while (count--) {
12969     int c;
12970
12971     if (ptr >= end)
12972       return -1;
12973
12974     c = *ptr++;
12975     len = (len << 7) | (c & 0x7f);
12976     if (!(c & 0x80))
12977       break;
12978   }
12979   *end_out = ptr;
12980   return len;
12981 }
12982
12983 /* this can change the codec originally present in @list */
12984 static void
12985 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
12986     GNode * esds, GstTagList * list)
12987 {
12988   int len = QT_UINT32 (esds->data);
12989   guint8 *ptr = esds->data;
12990   guint8 *end = ptr + len;
12991   int tag;
12992   guint8 *data_ptr = NULL;
12993   int data_len = 0;
12994   guint8 object_type_id = 0;
12995   const char *codec_name = NULL;
12996   GstCaps *caps = NULL;
12997
12998   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
12999   ptr += 8;
13000   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13001   ptr += 4;
13002   while (ptr + 1 < end) {
13003     tag = QT_UINT8 (ptr);
13004     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13005     ptr++;
13006     len = read_descr_size (ptr, end, &ptr);
13007     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13008
13009     /* Check the stated amount of data is available for reading */
13010     if (len < 0 || ptr + len > end)
13011       break;
13012
13013     switch (tag) {
13014       case ES_DESCRIPTOR_TAG:
13015         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13016         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13017         ptr += 3;
13018         break;
13019       case DECODER_CONFIG_DESC_TAG:{
13020         guint max_bitrate, avg_bitrate;
13021
13022         object_type_id = QT_UINT8 (ptr);
13023         max_bitrate = QT_UINT32 (ptr + 5);
13024         avg_bitrate = QT_UINT32 (ptr + 9);
13025         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13026         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13027         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13028         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13029         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13030         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13031           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13032               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13033         }
13034         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13035           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13036               avg_bitrate, NULL);
13037         }
13038         ptr += 13;
13039         break;
13040       }
13041       case DECODER_SPECIFIC_INFO_TAG:
13042         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13043         if (object_type_id == 0xe0 && len == 0x40) {
13044           guint8 *data;
13045           GstStructure *s;
13046           guint32 clut[16];
13047           gint i;
13048
13049           GST_DEBUG_OBJECT (qtdemux,
13050               "Have VOBSUB palette. Creating palette event");
13051           /* move to decConfigDescr data and read palette */
13052           data = ptr;
13053           for (i = 0; i < 16; i++) {
13054             clut[i] = QT_UINT32 (data);
13055             data += 4;
13056           }
13057
13058           s = gst_structure_new ("application/x-gst-dvd", "event",
13059               G_TYPE_STRING, "dvd-spu-clut-change",
13060               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13061               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13062               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13063               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13064               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13065               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13066               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13067               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13068               NULL);
13069
13070           /* store event and trigger custom processing */
13071           stream->pending_event =
13072               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13073         } else {
13074           /* Generic codec_data handler puts it on the caps */
13075           data_ptr = ptr;
13076           data_len = len;
13077         }
13078
13079         ptr += len;
13080         break;
13081       case SL_CONFIG_DESC_TAG:
13082         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13083         ptr += 1;
13084         break;
13085       default:
13086         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13087             tag);
13088         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13089         ptr += len;
13090         break;
13091     }
13092   }
13093
13094   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13095    * in use, and should also be used to override some other parameters for some
13096    * codecs. */
13097   switch (object_type_id) {
13098     case 0x20:                 /* MPEG-4 */
13099       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13100        * profile_and_level_indication */
13101       if (data_ptr != NULL && data_len >= 5 &&
13102           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13103         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
13104             data_ptr + 4, data_len - 4);
13105       }
13106       break;                    /* Nothing special needed here */
13107     case 0x21:                 /* H.264 */
13108       codec_name = "H.264 / AVC";
13109       caps = gst_caps_new_simple ("video/x-h264",
13110           "stream-format", G_TYPE_STRING, "avc",
13111           "alignment", G_TYPE_STRING, "au", NULL);
13112       break;
13113     case 0x40:                 /* AAC (any) */
13114     case 0x66:                 /* AAC Main */
13115     case 0x67:                 /* AAC LC */
13116     case 0x68:                 /* AAC SSR */
13117       /* Override channels and rate based on the codec_data, as it's often
13118        * wrong. */
13119       /* Only do so for basic setup without HE-AAC extension */
13120       if (data_ptr && data_len == 2) {
13121         guint channels, rate;
13122
13123         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13124         if (channels > 0)
13125           stream->n_channels = channels;
13126
13127         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13128         if (rate > 0)
13129           stream->rate = rate;
13130       }
13131
13132       /* Set level and profile if possible */
13133       if (data_ptr != NULL && data_len >= 2) {
13134         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
13135             data_ptr, data_len);
13136       } else {
13137         const gchar *profile_str = NULL;
13138         GstBuffer *buffer;
13139         GstMapInfo map;
13140         guint8 *codec_data;
13141         gint rate_idx, profile;
13142
13143         /* No codec_data, let's invent something.
13144          * FIXME: This is wrong for SBR! */
13145
13146         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13147
13148         buffer = gst_buffer_new_and_alloc (2);
13149         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13150         codec_data = map.data;
13151
13152         rate_idx =
13153             gst_codec_utils_aac_get_index_from_sample_rate (stream->rate);
13154
13155         switch (object_type_id) {
13156           case 0x66:
13157             profile_str = "main";
13158             profile = 0;
13159             break;
13160           case 0x67:
13161             profile_str = "lc";
13162             profile = 1;
13163             break;
13164           case 0x68:
13165             profile_str = "ssr";
13166             profile = 2;
13167             break;
13168           default:
13169             profile = 3;
13170             break;
13171         }
13172
13173         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13174         codec_data[1] = ((rate_idx & 0x1) << 7) | (stream->n_channels << 3);
13175
13176         gst_buffer_unmap (buffer, &map);
13177         gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13178             buffer, NULL);
13179         gst_buffer_unref (buffer);
13180
13181         if (profile_str) {
13182           gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
13183               profile_str, NULL);
13184         }
13185       }
13186       break;
13187     case 0x60:                 /* MPEG-2, various profiles */
13188     case 0x61:
13189     case 0x62:
13190     case 0x63:
13191     case 0x64:
13192     case 0x65:
13193       codec_name = "MPEG-2 video";
13194       caps = gst_caps_new_simple ("video/mpeg",
13195           "mpegversion", G_TYPE_INT, 2,
13196           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13197       break;
13198     case 0x69:                 /* MPEG-2 BC audio */
13199     case 0x6B:                 /* MPEG-1 audio */
13200       caps = gst_caps_new_simple ("audio/mpeg",
13201           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13202       codec_name = "MPEG-1 audio";
13203       break;
13204     case 0x6A:                 /* MPEG-1 */
13205       codec_name = "MPEG-1 video";
13206       caps = gst_caps_new_simple ("video/mpeg",
13207           "mpegversion", G_TYPE_INT, 1,
13208           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13209       break;
13210     case 0x6C:                 /* MJPEG */
13211       caps =
13212           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13213           NULL);
13214       codec_name = "Motion-JPEG";
13215       break;
13216     case 0x6D:                 /* PNG */
13217       caps =
13218           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13219           NULL);
13220       codec_name = "PNG still images";
13221       break;
13222     case 0x6E:                 /* JPEG2000 */
13223       codec_name = "JPEG-2000";
13224       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13225       break;
13226     case 0xA4:                 /* Dirac */
13227       codec_name = "Dirac";
13228       caps = gst_caps_new_empty_simple ("video/x-dirac");
13229       break;
13230     case 0xA5:                 /* AC3 */
13231       codec_name = "AC-3 audio";
13232       caps = gst_caps_new_simple ("audio/x-ac3",
13233           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13234       break;
13235     case 0xA9:                 /* AC3 */
13236       codec_name = "DTS audio";
13237       caps = gst_caps_new_simple ("audio/x-dts",
13238           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13239       break;
13240     case 0xE1:                 /* QCELP */
13241       /* QCELP, the codec_data is a riff tag (little endian) with
13242        * 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). */
13243       caps = gst_caps_new_empty_simple ("audio/qcelp");
13244       codec_name = "QCELP";
13245       break;
13246     default:
13247       break;
13248   }
13249
13250   /* If we have a replacement caps, then change our caps for this stream */
13251   if (caps) {
13252     gst_caps_unref (stream->caps);
13253     stream->caps = caps;
13254   }
13255
13256   if (codec_name && list)
13257     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13258         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13259
13260   /* Add the codec_data attribute to caps, if we have it */
13261   if (data_ptr) {
13262     GstBuffer *buffer;
13263
13264     buffer = gst_buffer_new_and_alloc (data_len);
13265     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13266
13267     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13268     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13269
13270     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
13271         buffer, NULL);
13272     gst_buffer_unref (buffer);
13273   }
13274
13275 }
13276
13277 static inline GstCaps *
13278 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13279 {
13280   GstCaps *caps;
13281   guint i;
13282   char *s, fourstr[5];
13283
13284   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13285   for (i = 0; i < 4; i++) {
13286     if (!g_ascii_isalnum (fourstr[i]))
13287       fourstr[i] = '_';
13288   }
13289   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13290   caps = gst_caps_new_empty_simple (s);
13291   g_free (s);
13292   return caps;
13293 }
13294
13295 #define _codec(name) \
13296   do { \
13297     if (codec_name) { \
13298       *codec_name = g_strdup (name); \
13299     } \
13300   } while (0)
13301
13302 static GstCaps *
13303 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13304     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
13305 {
13306   GstCaps *caps = NULL;
13307   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13308
13309   switch (fourcc) {
13310     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13311       _codec ("PNG still images");
13312       caps = gst_caps_new_empty_simple ("image/png");
13313       break;
13314     case FOURCC_jpeg:
13315       _codec ("JPEG still images");
13316       caps =
13317           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13318           NULL);
13319       break;
13320     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13321     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13322     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13323     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13324       _codec ("Motion-JPEG");
13325       caps =
13326           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13327           NULL);
13328       break;
13329     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13330       _codec ("Motion-JPEG format B");
13331       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13332       break;
13333     case FOURCC_mjp2:
13334       _codec ("JPEG-2000");
13335       /* override to what it should be according to spec, avoid palette_data */
13336       stream->bits_per_sample = 24;
13337       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13338       break;
13339     case FOURCC_SVQ3:
13340       _codec ("Sorensen video v.3");
13341       caps = gst_caps_new_simple ("video/x-svq",
13342           "svqversion", G_TYPE_INT, 3, NULL);
13343       break;
13344     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13345     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13346       _codec ("Sorensen video v.1");
13347       caps = gst_caps_new_simple ("video/x-svq",
13348           "svqversion", G_TYPE_INT, 1, NULL);
13349       break;
13350     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13351       caps = gst_caps_new_empty_simple ("video/x-raw");
13352       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13353       _codec ("Windows Raw RGB");
13354       stream->alignment = 32;
13355       break;
13356     case FOURCC_raw_:
13357     {
13358       guint16 bps;
13359
13360       bps = QT_UINT16 (stsd_data + 98);
13361       switch (bps) {
13362         case 15:
13363           format = GST_VIDEO_FORMAT_RGB15;
13364           break;
13365         case 16:
13366           format = GST_VIDEO_FORMAT_RGB16;
13367           break;
13368         case 24:
13369           format = GST_VIDEO_FORMAT_RGB;
13370           break;
13371         case 32:
13372           format = GST_VIDEO_FORMAT_ARGB;
13373           break;
13374         default:
13375           /* unknown */
13376           break;
13377       }
13378       break;
13379     }
13380     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13381       format = GST_VIDEO_FORMAT_I420;
13382       break;
13383     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13384     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13385       format = GST_VIDEO_FORMAT_I420;
13386       break;
13387     case FOURCC_2vuy:
13388     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13389       format = GST_VIDEO_FORMAT_UYVY;
13390       break;
13391     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13392       format = GST_VIDEO_FORMAT_v308;
13393       break;
13394     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13395       format = GST_VIDEO_FORMAT_v216;
13396       break;
13397     case FOURCC_v210:
13398       format = GST_VIDEO_FORMAT_v210;
13399       break;
13400     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13401       format = GST_VIDEO_FORMAT_r210;
13402       break;
13403       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13404          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13405          format = GST_VIDEO_FORMAT_v410;
13406          break;
13407        */
13408       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13409        * but different order than AYUV
13410        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13411        format = GST_VIDEO_FORMAT_v408;
13412        break;
13413        */
13414     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13415     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13416       _codec ("MPEG-1 video");
13417       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13418           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13419       break;
13420     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13421     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13422     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13423     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13424     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13425     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13426     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13427     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13428     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13429     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13430     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13431     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13432     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13433     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13434     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13435     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13436     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13437     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13438     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13439     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13440     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13441     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13442     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13443     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13444     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13445     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13446     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13447     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13448     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13449     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13450     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13451     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13452     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13453     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13454     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13455     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13456     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13457     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13458     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13459     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13460     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13461     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13462     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13463     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13464     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13465     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13466     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13467       _codec ("MPEG-2 video");
13468       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13469           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13470       break;
13471     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13472       _codec ("GIF still images");
13473       caps = gst_caps_new_empty_simple ("image/gif");
13474       break;
13475     case FOURCC_h263:
13476     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13477     case FOURCC_s263:
13478     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13479       _codec ("H.263");
13480       /* ffmpeg uses the height/width props, don't know why */
13481       caps = gst_caps_new_simple ("video/x-h263",
13482           "variant", G_TYPE_STRING, "itu", NULL);
13483       break;
13484     case FOURCC_mp4v:
13485     case FOURCC_MP4V:
13486       _codec ("MPEG-4 video");
13487       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13488           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13489       break;
13490     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13491     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13492       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13493       caps = gst_caps_new_simple ("video/x-msmpeg",
13494           "msmpegversion", G_TYPE_INT, 43, NULL);
13495       break;
13496     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13497       _codec ("DivX 3");
13498       caps = gst_caps_new_simple ("video/x-divx",
13499           "divxversion", G_TYPE_INT, 3, NULL);
13500       break;
13501     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13502     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13503       _codec ("DivX 4");
13504       caps = gst_caps_new_simple ("video/x-divx",
13505           "divxversion", G_TYPE_INT, 4, NULL);
13506       break;
13507     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13508       _codec ("DivX 5");
13509       caps = gst_caps_new_simple ("video/x-divx",
13510           "divxversion", G_TYPE_INT, 5, NULL);
13511       break;
13512
13513     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13514       _codec ("FFV1");
13515       caps = gst_caps_new_simple ("video/x-ffv",
13516           "ffvversion", G_TYPE_INT, 1, NULL);
13517       break;
13518
13519     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13520     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13521     case FOURCC_XVID:
13522     case FOURCC_xvid:
13523     case FOURCC_FMP4:
13524     case FOURCC_fmp4:
13525     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13526       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13527           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13528       _codec ("MPEG-4");
13529       break;
13530
13531     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13532       _codec ("Cinepak");
13533       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13534       break;
13535     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13536       _codec ("Apple QuickDraw");
13537       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13538       break;
13539     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13540       _codec ("Apple video");
13541       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13542       break;
13543     case FOURCC_H264:
13544     case FOURCC_avc1:
13545       _codec ("H.264 / AVC");
13546       caps = gst_caps_new_simple ("video/x-h264",
13547           "stream-format", G_TYPE_STRING, "avc",
13548           "alignment", G_TYPE_STRING, "au", NULL);
13549       break;
13550     case FOURCC_avc3:
13551       _codec ("H.264 / AVC");
13552       caps = gst_caps_new_simple ("video/x-h264",
13553           "stream-format", G_TYPE_STRING, "avc3",
13554           "alignment", G_TYPE_STRING, "au", NULL);
13555       break;
13556     case FOURCC_H265:
13557     case FOURCC_hvc1:
13558       _codec ("H.265 / HEVC");
13559       caps = gst_caps_new_simple ("video/x-h265",
13560           "stream-format", G_TYPE_STRING, "hvc1",
13561           "alignment", G_TYPE_STRING, "au", NULL);
13562       break;
13563     case FOURCC_hev1:
13564       _codec ("H.265 / HEVC");
13565       caps = gst_caps_new_simple ("video/x-h265",
13566           "stream-format", G_TYPE_STRING, "hev1",
13567           "alignment", G_TYPE_STRING, "au", NULL);
13568       break;
13569     case FOURCC_rle_:
13570       _codec ("Run-length encoding");
13571       caps = gst_caps_new_simple ("video/x-rle",
13572           "layout", G_TYPE_STRING, "quicktime", NULL);
13573       break;
13574     case FOURCC_WRLE:
13575       _codec ("Run-length encoding");
13576       caps = gst_caps_new_simple ("video/x-rle",
13577           "layout", G_TYPE_STRING, "microsoft", NULL);
13578       break;
13579     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13580     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13581       _codec ("Indeo Video 3");
13582       caps = gst_caps_new_simple ("video/x-indeo",
13583           "indeoversion", G_TYPE_INT, 3, NULL);
13584       break;
13585     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13586     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13587       _codec ("Intel Video 4");
13588       caps = gst_caps_new_simple ("video/x-indeo",
13589           "indeoversion", G_TYPE_INT, 4, NULL);
13590       break;
13591     case FOURCC_dvcp:
13592     case FOURCC_dvc_:
13593     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13594     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13595     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13596     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13597     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13598     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13599       _codec ("DV Video");
13600       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13601           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13602       break;
13603     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13604     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13605       _codec ("DVCPro50 Video");
13606       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13607           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13608       break;
13609     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13610     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13611       _codec ("DVCProHD Video");
13612       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13613           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13614       break;
13615     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13616       _codec ("Apple Graphics (SMC)");
13617       caps = gst_caps_new_empty_simple ("video/x-smc");
13618       break;
13619     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13620       _codec ("VP3");
13621       caps = gst_caps_new_empty_simple ("video/x-vp3");
13622       break;
13623     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13624       _codec ("VP6 Flash");
13625       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13626       break;
13627     case FOURCC_XiTh:
13628       _codec ("Theora");
13629       caps = gst_caps_new_empty_simple ("video/x-theora");
13630       /* theora uses one byte of padding in the data stream because it does not
13631        * allow 0 sized packets while theora does */
13632       stream->padding = 1;
13633       break;
13634     case FOURCC_drac:
13635       _codec ("Dirac");
13636       caps = gst_caps_new_empty_simple ("video/x-dirac");
13637       break;
13638     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13639       _codec ("TIFF still images");
13640       caps = gst_caps_new_empty_simple ("image/tiff");
13641       break;
13642     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13643       _codec ("Apple Intermediate Codec");
13644       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13645       break;
13646     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13647       _codec ("AVID DNxHD");
13648       caps = gst_caps_from_string ("video/x-dnxhd");
13649       break;
13650     case FOURCC_VP80:
13651       _codec ("On2 VP8");
13652       caps = gst_caps_from_string ("video/x-vp8");
13653       break;
13654     case FOURCC_apcs:
13655       _codec ("Apple ProRes LT");
13656       caps =
13657           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13658           NULL);
13659       break;
13660     case FOURCC_apch:
13661       _codec ("Apple ProRes HQ");
13662       caps =
13663           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13664           NULL);
13665       break;
13666     case FOURCC_apcn:
13667       _codec ("Apple ProRes");
13668       caps =
13669           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13670           "standard", NULL);
13671       break;
13672     case FOURCC_apco:
13673       _codec ("Apple ProRes Proxy");
13674       caps =
13675           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13676           "proxy", NULL);
13677       break;
13678     case FOURCC_ap4h:
13679       _codec ("Apple ProRes 4444");
13680       caps =
13681           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13682           "4444", NULL);
13683       break;
13684     case FOURCC_ap4x:
13685       _codec ("Apple ProRes 4444 XQ");
13686       caps =
13687           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13688           "4444xq", NULL);
13689       break;
13690     case FOURCC_vc_1:
13691     case FOURCC_ovc1:
13692       _codec ("VC-1");
13693       caps = gst_caps_new_simple ("video/x-wmv",
13694           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13695       break;
13696     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13697     default:
13698     {
13699       caps = _get_unknown_codec_name ("video", fourcc);
13700       break;
13701     }
13702   }
13703
13704   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13705     GstVideoInfo info;
13706
13707     gst_video_info_init (&info);
13708     gst_video_info_set_format (&info, format, stream->width, stream->height);
13709
13710     caps = gst_video_info_to_caps (&info);
13711     *codec_name = gst_pb_utils_get_codec_description (caps);
13712
13713     /* enable clipping for raw video streams */
13714     stream->need_clip = TRUE;
13715     stream->alignment = 32;
13716   }
13717
13718   return caps;
13719 }
13720
13721 static guint
13722 round_up_pow2 (guint n)
13723 {
13724   n = n - 1;
13725   n = n | (n >> 1);
13726   n = n | (n >> 2);
13727   n = n | (n >> 4);
13728   n = n | (n >> 8);
13729   n = n | (n >> 16);
13730   return n + 1;
13731 }
13732
13733 static GstCaps *
13734 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13735     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
13736 {
13737   GstCaps *caps;
13738   const GstStructure *s;
13739   const gchar *name;
13740   gint endian = 0;
13741   GstAudioFormat format = 0;
13742   gint depth;
13743
13744   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13745
13746   depth = stream->bytes_per_packet * 8;
13747
13748   switch (fourcc) {
13749     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13750     case FOURCC_raw_:
13751       /* 8-bit audio is unsigned */
13752       if (depth == 8)
13753         format = GST_AUDIO_FORMAT_U8;
13754       /* otherwise it's signed and big-endian just like 'twos' */
13755     case FOURCC_twos:
13756       endian = G_BIG_ENDIAN;
13757       /* fall-through */
13758     case FOURCC_sowt:
13759     {
13760       gchar *str;
13761
13762       if (!endian)
13763         endian = G_LITTLE_ENDIAN;
13764
13765       if (!format)
13766         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13767
13768       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13769       _codec (str);
13770       g_free (str);
13771
13772       caps = gst_caps_new_simple ("audio/x-raw",
13773           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13774           "layout", G_TYPE_STRING, "interleaved", NULL);
13775       stream->alignment = GST_ROUND_UP_8 (depth);
13776       stream->alignment = round_up_pow2 (stream->alignment);
13777       break;
13778     }
13779     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
13780       _codec ("Raw 64-bit floating-point audio");
13781       caps = gst_caps_new_simple ("audio/x-raw",
13782           "format", G_TYPE_STRING, "F64BE",
13783           "layout", G_TYPE_STRING, "interleaved", NULL);
13784       stream->alignment = 8;
13785       break;
13786     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
13787       _codec ("Raw 32-bit floating-point audio");
13788       caps = gst_caps_new_simple ("audio/x-raw",
13789           "format", G_TYPE_STRING, "F32BE",
13790           "layout", G_TYPE_STRING, "interleaved", NULL);
13791       stream->alignment = 4;
13792       break;
13793     case FOURCC_in24:
13794       _codec ("Raw 24-bit PCM audio");
13795       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
13796        * endian later */
13797       caps = gst_caps_new_simple ("audio/x-raw",
13798           "format", G_TYPE_STRING, "S24BE",
13799           "layout", G_TYPE_STRING, "interleaved", NULL);
13800       stream->alignment = 4;
13801       break;
13802     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
13803       _codec ("Raw 32-bit PCM audio");
13804       caps = gst_caps_new_simple ("audio/x-raw",
13805           "format", G_TYPE_STRING, "S32BE",
13806           "layout", G_TYPE_STRING, "interleaved", NULL);
13807       stream->alignment = 4;
13808       break;
13809     case FOURCC_ulaw:
13810       _codec ("Mu-law audio");
13811       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
13812       break;
13813     case FOURCC_alaw:
13814       _codec ("A-law audio");
13815       caps = gst_caps_new_empty_simple ("audio/x-alaw");
13816       break;
13817     case 0x0200736d:
13818     case 0x6d730002:
13819       _codec ("Microsoft ADPCM");
13820       /* Microsoft ADPCM-ACM code 2 */
13821       caps = gst_caps_new_simple ("audio/x-adpcm",
13822           "layout", G_TYPE_STRING, "microsoft", NULL);
13823       break;
13824     case 0x1100736d:
13825     case 0x6d730011:
13826       _codec ("DVI/IMA ADPCM");
13827       caps = gst_caps_new_simple ("audio/x-adpcm",
13828           "layout", G_TYPE_STRING, "dvi", NULL);
13829       break;
13830     case 0x1700736d:
13831     case 0x6d730017:
13832       _codec ("DVI/Intel IMA ADPCM");
13833       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
13834       caps = gst_caps_new_simple ("audio/x-adpcm",
13835           "layout", G_TYPE_STRING, "quicktime", NULL);
13836       break;
13837     case 0x5500736d:
13838     case 0x6d730055:
13839       /* MPEG layer 3, CBR only (pre QT4.1) */
13840     case FOURCC__mp3:
13841       _codec ("MPEG-1 layer 3");
13842       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
13843       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
13844           "mpegversion", G_TYPE_INT, 1, NULL);
13845       break;
13846     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
13847       _codec ("MPEG-1 layer 2");
13848       /* MPEG layer 2 */
13849       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
13850           "mpegversion", G_TYPE_INT, 1, NULL);
13851       break;
13852     case 0x20736d:
13853     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
13854       _codec ("EAC-3 audio");
13855       caps = gst_caps_new_simple ("audio/x-eac3",
13856           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13857       stream->sampled = TRUE;
13858       break;
13859     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
13860     case FOURCC_ac_3:
13861       _codec ("AC-3 audio");
13862       caps = gst_caps_new_simple ("audio/x-ac3",
13863           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13864       stream->sampled = TRUE;
13865       break;
13866     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
13867     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
13868       _codec ("DTS audio");
13869       caps = gst_caps_new_simple ("audio/x-dts",
13870           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13871       stream->sampled = TRUE;
13872       break;
13873     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
13874     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
13875       _codec ("DTS-HD audio");
13876       caps = gst_caps_new_simple ("audio/x-dts",
13877           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13878       stream->sampled = TRUE;
13879       break;
13880     case FOURCC_MAC3:
13881       _codec ("MACE-3");
13882       caps = gst_caps_new_simple ("audio/x-mace",
13883           "maceversion", G_TYPE_INT, 3, NULL);
13884       break;
13885     case FOURCC_MAC6:
13886       _codec ("MACE-6");
13887       caps = gst_caps_new_simple ("audio/x-mace",
13888           "maceversion", G_TYPE_INT, 6, NULL);
13889       break;
13890     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
13891       /* ogg/vorbis */
13892       caps = gst_caps_new_empty_simple ("application/ogg");
13893       break;
13894     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
13895       _codec ("DV audio");
13896       caps = gst_caps_new_empty_simple ("audio/x-dv");
13897       break;
13898     case FOURCC_mp4a:
13899       _codec ("MPEG-4 AAC audio");
13900       caps = gst_caps_new_simple ("audio/mpeg",
13901           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
13902           "stream-format", G_TYPE_STRING, "raw", NULL);
13903       break;
13904     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
13905       _codec ("QDesign Music");
13906       caps = gst_caps_new_empty_simple ("audio/x-qdm");
13907       break;
13908     case FOURCC_QDM2:
13909       _codec ("QDesign Music v.2");
13910       /* FIXME: QDesign music version 2 (no constant) */
13911       if (FALSE && data) {
13912         caps = gst_caps_new_simple ("audio/x-qdm2",
13913             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
13914             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
13915             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
13916       } else {
13917         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
13918       }
13919       break;
13920     case FOURCC_agsm:
13921       _codec ("GSM audio");
13922       caps = gst_caps_new_empty_simple ("audio/x-gsm");
13923       break;
13924     case FOURCC_samr:
13925       _codec ("AMR audio");
13926       caps = gst_caps_new_empty_simple ("audio/AMR");
13927       break;
13928     case FOURCC_sawb:
13929       _codec ("AMR-WB audio");
13930       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
13931       break;
13932     case FOURCC_ima4:
13933       _codec ("Quicktime IMA ADPCM");
13934       caps = gst_caps_new_simple ("audio/x-adpcm",
13935           "layout", G_TYPE_STRING, "quicktime", NULL);
13936       break;
13937     case FOURCC_alac:
13938       _codec ("Apple lossless audio");
13939       caps = gst_caps_new_empty_simple ("audio/x-alac");
13940       break;
13941     case FOURCC_fLaC:
13942       _codec ("Free Lossless Audio Codec");
13943       caps = gst_caps_new_simple ("audio/x-flac",
13944           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13945       break;
13946     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
13947       _codec ("QualComm PureVoice");
13948       caps = gst_caps_from_string ("audio/qcelp");
13949       break;
13950     case FOURCC_wma_:
13951     case FOURCC_owma:
13952       _codec ("WMA");
13953       caps = gst_caps_new_empty_simple ("audio/x-wma");
13954       break;
13955     case FOURCC_opus:
13956       _codec ("Opus");
13957       caps = gst_caps_new_empty_simple ("audio/x-opus");
13958       break;
13959     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
13960     {
13961       guint32 flags = 0;
13962       guint32 depth = 0;
13963       guint32 width = 0;
13964       GstAudioFormat format;
13965       enum
13966       {
13967         FLAG_IS_FLOAT = 0x1,
13968         FLAG_IS_BIG_ENDIAN = 0x2,
13969         FLAG_IS_SIGNED = 0x4,
13970         FLAG_IS_PACKED = 0x8,
13971         FLAG_IS_ALIGNED_HIGH = 0x10,
13972         FLAG_IS_NON_INTERLEAVED = 0x20
13973       };
13974       _codec ("Raw LPCM audio");
13975
13976       if (data && len >= 56) {
13977         depth = QT_UINT32 (data + 40);
13978         flags = QT_UINT32 (data + 44);
13979         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
13980       }
13981       if ((flags & FLAG_IS_FLOAT) == 0) {
13982         if (depth == 0)
13983           depth = 16;
13984         if (width == 0)
13985           width = 16;
13986         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
13987             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
13988             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
13989         caps = gst_caps_new_simple ("audio/x-raw",
13990             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
13991             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
13992             "non-interleaved" : "interleaved", NULL);
13993         stream->alignment = GST_ROUND_UP_8 (depth);
13994         stream->alignment = round_up_pow2 (stream->alignment);
13995       } else {
13996         if (width == 0)
13997           width = 32;
13998         if (width == 64) {
13999           if (flags & FLAG_IS_BIG_ENDIAN)
14000             format = GST_AUDIO_FORMAT_F64BE;
14001           else
14002             format = GST_AUDIO_FORMAT_F64LE;
14003         } else {
14004           if (flags & FLAG_IS_BIG_ENDIAN)
14005             format = GST_AUDIO_FORMAT_F32BE;
14006           else
14007             format = GST_AUDIO_FORMAT_F32LE;
14008         }
14009         caps = gst_caps_new_simple ("audio/x-raw",
14010             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14011             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14012             "non-interleaved" : "interleaved", NULL);
14013         stream->alignment = width / 8;
14014       }
14015       break;
14016     }
14017     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14018       /* ? */
14019     default:
14020     {
14021       caps = _get_unknown_codec_name ("audio", fourcc);
14022       break;
14023     }
14024   }
14025
14026   if (caps) {
14027     GstCaps *templ_caps =
14028         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14029     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14030     gst_caps_unref (caps);
14031     gst_caps_unref (templ_caps);
14032     caps = intersection;
14033   }
14034
14035   /* enable clipping for raw audio streams */
14036   s = gst_caps_get_structure (caps, 0);
14037   name = gst_structure_get_name (s);
14038   if (g_str_has_prefix (name, "audio/x-raw")) {
14039     stream->need_clip = TRUE;
14040     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
14041     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14042   }
14043   return caps;
14044 }
14045
14046 static GstCaps *
14047 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14048     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
14049 {
14050   GstCaps *caps;
14051
14052   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14053
14054   switch (fourcc) {
14055     case FOURCC_mp4s:
14056       _codec ("DVD subtitle");
14057       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14058       stream->need_process = TRUE;
14059       break;
14060     case FOURCC_text:
14061       _codec ("Quicktime timed text");
14062       goto text;
14063     case FOURCC_tx3g:
14064       _codec ("3GPP timed text");
14065     text:
14066       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14067           "utf8", NULL);
14068       /* actual text piece needs to be extracted */
14069       stream->need_process = TRUE;
14070       break;
14071     case FOURCC_stpp:
14072       _codec ("XML subtitles");
14073       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14074       break;
14075     default:
14076     {
14077       caps = _get_unknown_codec_name ("text", fourcc);
14078       break;
14079     }
14080   }
14081   return caps;
14082 }
14083
14084 static GstCaps *
14085 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14086     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
14087 {
14088   GstCaps *caps;
14089
14090   switch (fourcc) {
14091     case FOURCC_m1v:
14092       _codec ("MPEG 1 video");
14093       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14094           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14095       break;
14096     default:
14097       caps = NULL;
14098       break;
14099   }
14100   return caps;
14101 }
14102
14103 static void
14104 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14105     const gchar * system_id)
14106 {
14107   gint i;
14108
14109   if (!qtdemux->protection_system_ids)
14110     qtdemux->protection_system_ids =
14111         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14112   /* Check whether we already have an entry for this system ID. */
14113   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14114     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14115     if (g_ascii_strcasecmp (system_id, id) == 0) {
14116       return;
14117     }
14118   }
14119   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14120   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14121           -1));
14122 }