d7fdae822ade6c73b400d26ddcf2a5d6576b6e90
[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 QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 GST_DEBUG_CATEGORY (qtdemux_debug);
104
105 typedef struct _QtDemuxSegment QtDemuxSegment;
106 typedef struct _QtDemuxSample QtDemuxSample;
107
108 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
109
110 struct _QtDemuxSample
111 {
112   guint32 size;
113   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
114   guint64 offset;
115   guint64 timestamp;            /* DTS In mov time */
116   guint32 duration;             /* In mov time */
117   gboolean keyframe;            /* TRUE when this packet is a keyframe */
118 };
119
120 /* Macros for converting to/from timescale */
121 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
122 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
123
124 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
125 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
126
127 /* timestamp is the DTS */
128 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
129 /* timestamp + offset + cslg_shift is the outgoing PTS */
130 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
131 /* timestamp + offset is the PTS used for internal seek calcuations */
132 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
133 /* timestamp + duration - dts is the duration */
134 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
135
136 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
137
138 /*
139  * Quicktime has tracks and segments. A track is a continuous piece of
140  * multimedia content. The track is not always played from start to finish but
141  * instead, pieces of the track are 'cut out' and played in sequence. This is
142  * what the segments do.
143  *
144  * Inside the track we have keyframes (K) and delta frames. The track has its
145  * own timing, which starts from 0 and extends to end. The position in the track
146  * is called the media_time.
147  *
148  * The segments now describe the pieces that should be played from this track
149  * and are basically tuples of media_time/duration/rate entries. We can have
150  * multiple segments and they are all played after one another. An example:
151  *
152  * segment 1: media_time: 1 second, duration: 1 second, rate 1
153  * segment 2: media_time: 3 second, duration: 2 second, rate 2
154  *
155  * To correctly play back this track, one must play: 1 second of media starting
156  * from media_time 1 followed by 2 seconds of media starting from media_time 3
157  * at a rate of 2.
158  *
159  * Each of the segments will be played at a specific time, the first segment at
160  * time 0, the second one after the duration of the first one, etc.. Note that
161  * the time in resulting playback is not identical to the media_time of the
162  * track anymore.
163  *
164  * Visually, assuming the track has 4 second of media_time:
165  *
166  *                (a)                   (b)          (c)              (d)
167  *         .-----------------------------------------------------------.
168  * track:  | K.....K.........K........K.......K.......K...........K... |
169  *         '-----------------------------------------------------------'
170  *         0              1              2              3              4
171  *           .------------^              ^   .----------^              ^
172  *          /              .-------------'  /       .------------------'
173  *         /              /          .-----'       /
174  *         .--------------.         .--------------.
175  *         | segment 1    |         | segment 2    |
176  *         '--------------'         '--------------'
177  *
178  * The challenge here is to cut out the right pieces of the track for each of
179  * the playback segments. This fortunately can easily be done with the SEGMENT
180  * events of GStreamer.
181  *
182  * For playback of segment 1, we need to provide the decoder with the keyframe
183  * (a), in the above figure, but we must instruct it only to output the decoded
184  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
185  * position set to the time of the segment: 0.
186  *
187  * We then proceed to push data from keyframe (a) to frame (b). The decoder
188  * decodes but clips all before media_time 1.
189  *
190  * After finishing a segment, we push out a new SEGMENT event with the clipping
191  * boundaries of the new data.
192  *
193  * This is a good usecase for the GStreamer accumulated SEGMENT events.
194  */
195
196 struct _QtDemuxSegment
197 {
198   /* global time and duration, all gst time */
199   GstClockTime time;
200   GstClockTime stop_time;
201   GstClockTime duration;
202   /* media time of trak, all gst time */
203   GstClockTime media_start;
204   GstClockTime media_stop;
205   gdouble rate;
206   /* Media start time in trak timescale units */
207   guint32 trak_media_start;
208 };
209
210 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
211
212 /* Used with fragmented MP4 files (mfra atom) */
213 typedef struct
214 {
215   GstClockTime ts;
216   guint64 moof_offset;
217 } QtDemuxRandomAccessEntry;
218
219 typedef struct _QtDemuxStreamStsdEntry
220 {
221   GstCaps *caps;
222   guint32 fourcc;
223   gboolean sparse;
224
225   /* video info */
226   gint width;
227   gint height;
228   gint par_w;
229   gint par_h;
230   /* Numerator/denominator framerate */
231   gint fps_n;
232   gint fps_d;
233   GstVideoColorimetry colorimetry;
234   guint16 bits_per_sample;
235   guint16 color_table_id;
236   GstMemory *rgb8_palette;
237   guint interlace_mode;
238   guint field_order;
239
240   /* audio info */
241   gdouble rate;
242   gint n_channels;
243   guint samples_per_packet;
244   guint samples_per_frame;
245   guint bytes_per_packet;
246   guint bytes_per_sample;
247   guint bytes_per_frame;
248   guint compression;
249
250   /* if we use chunks or samples */
251   gboolean sampled;
252   guint padding;
253
254 } QtDemuxStreamStsdEntry;
255
256 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
257
258 struct _QtDemuxStream
259 {
260   GstPad *pad;
261
262   QtDemuxStreamStsdEntry *stsd_entries;
263   guint stsd_entries_length;
264   guint cur_stsd_entry_index;
265
266   /* stream type */
267   guint32 subtype;
268
269   gboolean new_caps;            /* If TRUE, caps need to be generated (by
270                                  * calling _configure_stream()) This happens
271                                  * for MSS and fragmented streams */
272
273   gboolean new_stream;          /* signals that a stream_start is required */
274   gboolean on_keyframe;         /* if this stream last pushed buffer was a
275                                  * keyframe. This is important to identify
276                                  * where to stop pushing buffers after a
277                                  * segment stop time */
278
279   /* if the stream has a redirect URI in its headers, we store it here */
280   gchar *redirect_uri;
281
282   /* track id */
283   guint track_id;
284
285   /* duration/scale */
286   guint64 duration;             /* in timescale units */
287   guint32 timescale;
288
289   /* language */
290   gchar lang_id[4];             /* ISO 639-2T language code */
291
292   /* our samples */
293   guint32 n_samples;
294   QtDemuxSample *samples;
295   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
296   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
297                                    the framerate */
298   guint32 n_samples_moof;       /* sample count in a moof */
299   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
300                                  * the framerate of fragmented format stream */
301   guint64 duration_last_moof;
302
303   guint32 offset_in_sample;     /* Offset in the current sample, used for
304                                  * streams which have got exceedingly big
305                                  * sample size (such as 24s of raw audio).
306                                  * Only used when max_buffer_size is non-NULL */
307   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
308                                  * Currently only set for raw audio streams*/
309
310   /* video info */
311   /* aspect ratio */
312   gint display_width;
313   gint display_height;
314
315   /* allocation */
316   gboolean use_allocator;
317   GstAllocator *allocator;
318   GstAllocationParams params;
319
320   gsize alignment;
321
322   /* when a discontinuity is pending */
323   gboolean discont;
324
325   /* list of buffers to push first */
326   GSList *buffers;
327
328   /* if we need to clip this buffer. This is only needed for uncompressed
329    * data */
330   gboolean need_clip;
331
332   /* buffer needs some custom processing, e.g. subtitles */
333   gboolean need_process;
334
335   /* current position */
336   guint32 segment_index;
337   guint32 sample_index;
338   GstClockTime time_position;   /* in gst time */
339   guint64 accumulated_base;
340
341   /* the Gst segment we are processing out, used for clipping */
342   GstSegment segment;
343
344   /* quicktime segments */
345   guint32 n_segments;
346   QtDemuxSegment *segments;
347   gboolean dummy_segment;
348   guint32 from_sample;
349   guint32 to_sample;
350
351   gboolean sent_eos;
352   GstTagList *stream_tags;
353   gboolean send_global_tags;
354
355   GstEvent *pending_event;
356
357   GstByteReader stco;
358   GstByteReader stsz;
359   GstByteReader stsc;
360   GstByteReader stts;
361   GstByteReader stss;
362   GstByteReader stps;
363   GstByteReader ctts;
364
365   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
366   gint64 stbl_index;
367   /* stco */
368   guint co_size;
369   GstByteReader co_chunk;
370   guint32 first_chunk;
371   guint32 current_chunk;
372   guint32 last_chunk;
373   guint32 samples_per_chunk;
374   guint32 stsd_sample_description_id;
375   guint32 stco_sample_index;
376   /* stsz */
377   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
378   /* stsc */
379   guint32 stsc_index;
380   guint32 n_samples_per_chunk;
381   guint32 stsc_chunk_index;
382   guint32 stsc_sample_index;
383   guint64 chunk_offset;
384   /* stts */
385   guint32 stts_index;
386   guint32 stts_samples;
387   guint32 n_sample_times;
388   guint32 stts_sample_index;
389   guint64 stts_time;
390   guint32 stts_duration;
391   /* stss */
392   gboolean stss_present;
393   guint32 n_sample_syncs;
394   guint32 stss_index;
395   /* stps */
396   gboolean stps_present;
397   guint32 n_sample_partial_syncs;
398   guint32 stps_index;
399   QtDemuxRandomAccessEntry *ra_entries;
400   guint n_ra_entries;
401
402   const QtDemuxRandomAccessEntry *pending_seek;
403
404   /* ctts */
405   gboolean ctts_present;
406   guint32 n_composition_times;
407   guint32 ctts_index;
408   guint32 ctts_sample_index;
409   guint32 ctts_count;
410   gint32 ctts_soffset;
411
412   /* cslg */
413   guint32 cslg_shift;
414
415   /* fragmented */
416   gboolean parsed_trex;
417   guint32 def_sample_duration;
418   guint32 def_sample_size;
419   guint32 def_sample_flags;
420
421   gboolean disabled;
422
423   /* stereoscopic video streams */
424   GstVideoMultiviewMode multiview_mode;
425   GstVideoMultiviewFlags multiview_flags;
426
427   /* protected streams */
428   gboolean protected;
429   guint32 protection_scheme_type;
430   guint32 protection_scheme_version;
431   gpointer protection_scheme_info;      /* specific to the protection scheme */
432   GQueue protection_scheme_event_queue;
433 };
434
435 /* Contains properties and cryptographic info for a set of samples from a
436  * track protected using Common Encryption (cenc) */
437 struct _QtDemuxCencSampleSetInfo
438 {
439   GstStructure *default_properties;
440
441   /* @crypto_info holds one GstStructure per sample */
442   GPtrArray *crypto_info;
443 };
444
445 static const gchar *
446 qt_demux_state_string (enum QtDemuxState state)
447 {
448   switch (state) {
449     case QTDEMUX_STATE_INITIAL:
450       return "<INITIAL>";
451     case QTDEMUX_STATE_HEADER:
452       return "<HEADER>";
453     case QTDEMUX_STATE_MOVIE:
454       return "<MOVIE>";
455     case QTDEMUX_STATE_BUFFER_MDAT:
456       return "<BUFFER_MDAT>";
457     default:
458       return "<UNKNOWN>";
459   }
460 }
461
462 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
463 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
464     guint32 fourcc, GstByteReader * parser);
465 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
466 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
467     guint32 fourcc, GstByteReader * parser);
468
469 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
470
471 static GstStaticPadTemplate gst_qtdemux_sink_template =
472     GST_STATIC_PAD_TEMPLATE ("sink",
473     GST_PAD_SINK,
474     GST_PAD_ALWAYS,
475     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
476         "application/x-3gp")
477     );
478
479 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
480 GST_STATIC_PAD_TEMPLATE ("video_%u",
481     GST_PAD_SRC,
482     GST_PAD_SOMETIMES,
483     GST_STATIC_CAPS_ANY);
484
485 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
486 GST_STATIC_PAD_TEMPLATE ("audio_%u",
487     GST_PAD_SRC,
488     GST_PAD_SOMETIMES,
489     GST_STATIC_CAPS_ANY);
490
491 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
492 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
493     GST_PAD_SRC,
494     GST_PAD_SOMETIMES,
495     GST_STATIC_CAPS_ANY);
496
497 #define gst_qtdemux_parent_class parent_class
498 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
499
500 static void gst_qtdemux_dispose (GObject * object);
501
502 static guint32
503 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
504     GstClockTime media_time);
505 static guint32
506 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
507     QtDemuxStream * str, gint64 media_offset);
508
509 #if 0
510 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
511 static GstIndex *gst_qtdemux_get_index (GstElement * element);
512 #endif
513 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
514     GstStateChange transition);
515 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
516 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
517     GstObject * parent, GstPadMode mode, gboolean active);
518
519 static void gst_qtdemux_loop (GstPad * pad);
520 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
521     GstBuffer * inbuf);
522 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
523     GstEvent * event);
524 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
525 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
526     QtDemuxStream * stream);
527 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
528     QtDemuxStream * stream);
529 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
530     gboolean force);
531
532 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
533     const guint8 * buffer, guint length);
534 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
535     const guint8 * buffer, guint length);
536 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
537 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
538     GNode * udta);
539
540 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
541     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
542     GstTagList * list);
543 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
544     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
545     const guint8 * stsd_entry_data, gchar ** codec_name);
546 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
547     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
548     const guint8 * data, int len, gchar ** codec_name);
549 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
550     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
551     gchar ** codec_name);
552 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
553     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
554     const guint8 * stsd_entry_data, gchar ** codec_name);
555
556 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
557     QtDemuxStream * stream, guint32 n);
558 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
559 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
560     QtDemuxStream * stream);
561 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
562     QtDemuxStream * stream);
563 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
564 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
565 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
566     QtDemuxStream * stream);
567 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
568     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
569 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
570     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
571     GstClockTime * _start, GstClockTime * _stop);
572 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
573     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
574
575 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
576 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
577
578 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
579
580 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
581     QtDemuxStream * stream, guint sample_index);
582 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
583     const gchar * id);
584 static void qtdemux_gst_structure_free (GstStructure * gststructure);
585
586 static void
587 gst_qtdemux_class_init (GstQTDemuxClass * klass)
588 {
589   GObjectClass *gobject_class;
590   GstElementClass *gstelement_class;
591
592   gobject_class = (GObjectClass *) klass;
593   gstelement_class = (GstElementClass *) klass;
594
595   parent_class = g_type_class_peek_parent (klass);
596
597   gobject_class->dispose = gst_qtdemux_dispose;
598
599   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
600 #if 0
601   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
602   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
603 #endif
604
605   gst_tag_register_musicbrainz_tags ();
606
607   gst_element_class_add_static_pad_template (gstelement_class,
608       &gst_qtdemux_sink_template);
609   gst_element_class_add_static_pad_template (gstelement_class,
610       &gst_qtdemux_videosrc_template);
611   gst_element_class_add_static_pad_template (gstelement_class,
612       &gst_qtdemux_audiosrc_template);
613   gst_element_class_add_static_pad_template (gstelement_class,
614       &gst_qtdemux_subsrc_template);
615   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
616       "Codec/Demuxer",
617       "Demultiplex a QuickTime file into audio and video streams",
618       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
619
620   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
621
622 }
623
624 static void
625 gst_qtdemux_init (GstQTDemux * qtdemux)
626 {
627   qtdemux->sinkpad =
628       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
629   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
630   gst_pad_set_activatemode_function (qtdemux->sinkpad,
631       qtdemux_sink_activate_mode);
632   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
633   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
634   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
635
636   qtdemux->state = QTDEMUX_STATE_INITIAL;
637   qtdemux->pullbased = FALSE;
638   qtdemux->posted_redirect = FALSE;
639   qtdemux->neededbytes = 16;
640   qtdemux->todrop = 0;
641   qtdemux->adapter = gst_adapter_new ();
642   qtdemux->offset = 0;
643   qtdemux->first_mdat = -1;
644   qtdemux->got_moov = FALSE;
645   qtdemux->mdatoffset = -1;
646   qtdemux->mdatbuffer = NULL;
647   qtdemux->restoredata_buffer = NULL;
648   qtdemux->restoredata_offset = -1;
649   qtdemux->fragment_start = -1;
650   qtdemux->fragment_start_offset = -1;
651   qtdemux->media_caps = NULL;
652   qtdemux->exposed = FALSE;
653   qtdemux->mss_mode = FALSE;
654   qtdemux->pending_newsegment = NULL;
655   qtdemux->upstream_format_is_time = FALSE;
656   qtdemux->have_group_id = FALSE;
657   qtdemux->group_id = G_MAXUINT;
658   qtdemux->cenc_aux_info_offset = 0;
659   qtdemux->cenc_aux_info_sizes = NULL;
660   qtdemux->cenc_aux_sample_count = 0;
661   qtdemux->protection_system_ids = NULL;
662   g_queue_init (&qtdemux->protection_event_queue);
663   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
664   qtdemux->tag_list = gst_tag_list_new_empty ();
665   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
666   qtdemux->flowcombiner = gst_flow_combiner_new ();
667
668   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
669 }
670
671 static void
672 gst_qtdemux_dispose (GObject * object)
673 {
674   GstQTDemux *qtdemux = GST_QTDEMUX (object);
675
676   if (qtdemux->adapter) {
677     g_object_unref (G_OBJECT (qtdemux->adapter));
678     qtdemux->adapter = NULL;
679   }
680   gst_tag_list_unref (qtdemux->tag_list);
681   gst_flow_combiner_free (qtdemux->flowcombiner);
682   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
683       NULL);
684   g_queue_clear (&qtdemux->protection_event_queue);
685
686   g_free (qtdemux->cenc_aux_info_sizes);
687   qtdemux->cenc_aux_info_sizes = NULL;
688
689   G_OBJECT_CLASS (parent_class)->dispose (object);
690 }
691
692 static void
693 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
694 {
695   if (qtdemux->posted_redirect) {
696     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
697         (_("This file contains no playable streams.")),
698         ("no known streams found, a redirect message has been posted"));
699   } else {
700     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
701         (_("This file contains no playable streams.")),
702         ("no known streams found"));
703   }
704 }
705
706 static GstBuffer *
707 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
708 {
709   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
710       mem, size, 0, size, mem, free_func);
711 }
712
713 static GstFlowReturn
714 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
715     GstBuffer ** buf)
716 {
717   GstFlowReturn flow;
718   GstMapInfo map;
719   gsize bsize;
720
721   if (G_UNLIKELY (size == 0)) {
722     GstFlowReturn ret;
723     GstBuffer *tmp = NULL;
724
725     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
726     if (ret != GST_FLOW_OK)
727       return ret;
728
729     gst_buffer_map (tmp, &map, GST_MAP_READ);
730     size = QT_UINT32 (map.data);
731     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
732
733     gst_buffer_unmap (tmp, &map);
734     gst_buffer_unref (tmp);
735   }
736
737   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
738   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
739     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
740       /* we're pulling header but already got most interesting bits,
741        * so never mind the rest (e.g. tags) (that much) */
742       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
743           size);
744       return GST_FLOW_EOS;
745     } else {
746       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
747           (_("This file is invalid and cannot be played.")),
748           ("atom has bogus size %" G_GUINT64_FORMAT, size));
749       return GST_FLOW_ERROR;
750     }
751   }
752
753   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
754
755   if (G_UNLIKELY (flow != GST_FLOW_OK))
756     return flow;
757
758   bsize = gst_buffer_get_size (*buf);
759   /* Catch short reads - we don't want any partial atoms */
760   if (G_UNLIKELY (bsize < size)) {
761     GST_WARNING_OBJECT (qtdemux,
762         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
763     gst_buffer_unref (*buf);
764     *buf = NULL;
765     return GST_FLOW_EOS;
766   }
767
768   return flow;
769 }
770
771 #if 1
772 static gboolean
773 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
774     GstFormat src_format, gint64 src_value, GstFormat dest_format,
775     gint64 * dest_value)
776 {
777   gboolean res = TRUE;
778   QtDemuxStream *stream = gst_pad_get_element_private (pad);
779   gint32 index;
780
781   if (stream->subtype != FOURCC_vide) {
782     res = FALSE;
783     goto done;
784   }
785
786   switch (src_format) {
787     case GST_FORMAT_TIME:
788       switch (dest_format) {
789         case GST_FORMAT_BYTES:{
790           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
791           if (-1 == index) {
792             res = FALSE;
793             goto done;
794           }
795
796           *dest_value = stream->samples[index].offset;
797
798           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
799               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
800               GST_TIME_ARGS (src_value), *dest_value);
801           break;
802         }
803         default:
804           res = FALSE;
805           break;
806       }
807       break;
808     case GST_FORMAT_BYTES:
809       switch (dest_format) {
810         case GST_FORMAT_TIME:{
811           index =
812               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
813               stream, src_value);
814
815           if (-1 == index) {
816             res = FALSE;
817             goto done;
818           }
819
820           *dest_value =
821               QTSTREAMTIME_TO_GSTTIME (stream,
822               stream->samples[index].timestamp);
823           GST_DEBUG_OBJECT (qtdemux,
824               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
825               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
826           break;
827         }
828         default:
829           res = FALSE;
830           break;
831       }
832       break;
833     default:
834       res = FALSE;
835       break;
836   }
837
838 done:
839   return res;
840 }
841 #endif
842
843 static gboolean
844 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
845 {
846   gboolean res = FALSE;
847
848   *duration = GST_CLOCK_TIME_NONE;
849
850   if (qtdemux->duration != 0 &&
851       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
852     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
853     res = TRUE;
854   } else {
855     *duration = GST_CLOCK_TIME_NONE;
856   }
857
858   return res;
859 }
860
861 static gboolean
862 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
863     GstQuery * query)
864 {
865   gboolean res = FALSE;
866   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
867
868   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
869
870   switch (GST_QUERY_TYPE (query)) {
871     case GST_QUERY_POSITION:{
872       GstFormat fmt;
873
874       gst_query_parse_position (query, &fmt, NULL);
875       if (fmt == GST_FORMAT_TIME
876           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
877         gst_query_set_position (query, GST_FORMAT_TIME,
878             qtdemux->segment.position);
879         res = TRUE;
880       }
881     }
882       break;
883     case GST_QUERY_DURATION:{
884       GstFormat fmt;
885
886       gst_query_parse_duration (query, &fmt, NULL);
887       if (fmt == GST_FORMAT_TIME) {
888         /* First try to query upstream */
889         res = gst_pad_query_default (pad, parent, query);
890         if (!res) {
891           GstClockTime duration;
892           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
893             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
894             res = TRUE;
895           }
896         }
897       }
898       break;
899     }
900     case GST_QUERY_CONVERT:{
901       GstFormat src_fmt, dest_fmt;
902       gint64 src_value, dest_value = 0;
903
904       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
905
906       res = gst_qtdemux_src_convert (qtdemux, pad,
907           src_fmt, src_value, dest_fmt, &dest_value);
908       if (res) {
909         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
910         res = TRUE;
911       }
912       break;
913     }
914     case GST_QUERY_FORMATS:
915       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
916       res = TRUE;
917       break;
918     case GST_QUERY_SEEKING:{
919       GstFormat fmt;
920       gboolean seekable;
921
922       /* try upstream first */
923       res = gst_pad_query_default (pad, parent, query);
924
925       if (!res) {
926         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
927         if (fmt == GST_FORMAT_TIME) {
928           GstClockTime duration;
929
930           gst_qtdemux_get_duration (qtdemux, &duration);
931           seekable = TRUE;
932           if (!qtdemux->pullbased) {
933             GstQuery *q;
934
935             /* we might be able with help from upstream */
936             seekable = FALSE;
937             q = gst_query_new_seeking (GST_FORMAT_BYTES);
938             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
939               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
940               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
941             }
942             gst_query_unref (q);
943           }
944           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
945           res = TRUE;
946         }
947       }
948       break;
949     }
950     case GST_QUERY_SEGMENT:
951     {
952       GstFormat format;
953       gint64 start, stop;
954
955       format = qtdemux->segment.format;
956
957       start =
958           gst_segment_to_stream_time (&qtdemux->segment, format,
959           qtdemux->segment.start);
960       if ((stop = qtdemux->segment.stop) == -1)
961         stop = qtdemux->segment.duration;
962       else
963         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
964
965       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
966       res = TRUE;
967       break;
968     }
969     default:
970       res = gst_pad_query_default (pad, parent, query);
971       break;
972   }
973
974   return res;
975 }
976
977 static void
978 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
979 {
980   if (G_LIKELY (stream->pad)) {
981     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
982         GST_DEBUG_PAD_NAME (stream->pad));
983
984     if (!gst_tag_list_is_empty (stream->stream_tags)) {
985       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
986           stream->stream_tags);
987       gst_pad_push_event (stream->pad,
988           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
989     }
990
991     if (G_UNLIKELY (stream->send_global_tags)) {
992       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
993           qtdemux->tag_list);
994       gst_pad_push_event (stream->pad,
995           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
996       stream->send_global_tags = FALSE;
997     }
998   }
999 }
1000
1001 /* push event on all source pads; takes ownership of the event */
1002 static void
1003 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1004 {
1005   guint n;
1006   gboolean has_valid_stream = FALSE;
1007   GstEventType etype = GST_EVENT_TYPE (event);
1008
1009   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1010       GST_EVENT_TYPE_NAME (event));
1011
1012   for (n = 0; n < qtdemux->n_streams; n++) {
1013     GstPad *pad;
1014     QtDemuxStream *stream = qtdemux->streams[n];
1015     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1016
1017     if ((pad = stream->pad)) {
1018       has_valid_stream = TRUE;
1019
1020       if (etype == GST_EVENT_EOS) {
1021         /* let's not send twice */
1022         if (stream->sent_eos)
1023           continue;
1024         stream->sent_eos = TRUE;
1025       }
1026
1027       gst_pad_push_event (pad, gst_event_ref (event));
1028     }
1029   }
1030
1031   gst_event_unref (event);
1032
1033   /* if it is EOS and there are no pads, post an error */
1034   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1035     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1036   }
1037 }
1038
1039 /* push a pending newsegment event, if any from the streaming thread */
1040 static void
1041 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1042 {
1043   if (qtdemux->pending_newsegment) {
1044     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1045     qtdemux->pending_newsegment = NULL;
1046   }
1047 }
1048
1049 typedef struct
1050 {
1051   guint64 media_time;
1052 } FindData;
1053
1054 static gint
1055 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1056 {
1057   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1058     return 1;
1059   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1060     return 0;
1061
1062   return -1;
1063 }
1064
1065 /* find the index of the sample that includes the data for @media_time using a
1066  * binary search.  Only to be called in optimized cases of linear search below.
1067  *
1068  * Returns the index of the sample.
1069  */
1070 static guint32
1071 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1072     guint64 media_time)
1073 {
1074   QtDemuxSample *result;
1075   guint32 index;
1076
1077   /* convert media_time to mov format */
1078   media_time =
1079       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1080
1081   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1082       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1083       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1084
1085   if (G_LIKELY (result))
1086     index = result - str->samples;
1087   else
1088     index = 0;
1089
1090   return index;
1091 }
1092
1093
1094
1095 /* find the index of the sample that includes the data for @media_offset using a
1096  * linear search
1097  *
1098  * Returns the index of the sample.
1099  */
1100 static guint32
1101 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1102     QtDemuxStream * str, gint64 media_offset)
1103 {
1104   QtDemuxSample *result = str->samples;
1105   guint32 index = 0;
1106
1107   if (result == NULL || str->n_samples == 0)
1108     return -1;
1109
1110   if (media_offset == result->offset)
1111     return index;
1112
1113   result++;
1114   while (index < str->n_samples - 1) {
1115     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1116       goto parse_failed;
1117
1118     if (media_offset < result->offset)
1119       break;
1120
1121     index++;
1122     result++;
1123   }
1124   return index;
1125
1126   /* ERRORS */
1127 parse_failed:
1128   {
1129     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1130     return -1;
1131   }
1132 }
1133
1134 /* find the index of the sample that includes the data for @media_time using a
1135  * linear search, and keeping in mind that not all samples may have been parsed
1136  * yet.  If possible, it will delegate to binary search.
1137  *
1138  * Returns the index of the sample.
1139  */
1140 static guint32
1141 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1142     GstClockTime media_time)
1143 {
1144   guint32 index = 0;
1145   guint64 mov_time;
1146   QtDemuxSample *sample;
1147
1148   /* convert media_time to mov format */
1149   mov_time =
1150       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1151
1152   sample = str->samples;
1153   if (mov_time == sample->timestamp + sample->pts_offset)
1154     return index;
1155
1156   /* use faster search if requested time in already parsed range */
1157   sample = str->samples + str->stbl_index;
1158   if (str->stbl_index >= 0 &&
1159       mov_time <= (sample->timestamp + sample->pts_offset))
1160     return gst_qtdemux_find_index (qtdemux, str, media_time);
1161
1162   while (index < str->n_samples - 1) {
1163     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1164       goto parse_failed;
1165
1166     sample = str->samples + index + 1;
1167     if (mov_time < (sample->timestamp + sample->pts_offset))
1168       break;
1169
1170     index++;
1171   }
1172   return index;
1173
1174   /* ERRORS */
1175 parse_failed:
1176   {
1177     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1178     return -1;
1179   }
1180 }
1181
1182 /* find the index of the keyframe needed to decode the sample at @index
1183  * of stream @str, or of a subsequent keyframe (depending on @next)
1184  *
1185  * Returns the index of the keyframe.
1186  */
1187 static guint32
1188 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1189     guint32 index, gboolean next)
1190 {
1191   guint32 new_index = index;
1192
1193   if (index >= str->n_samples) {
1194     new_index = str->n_samples;
1195     goto beach;
1196   }
1197
1198   /* all keyframes, return index */
1199   if (str->all_keyframe) {
1200     new_index = index;
1201     goto beach;
1202   }
1203
1204   /* else search until we have a keyframe */
1205   while (new_index < str->n_samples) {
1206     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1207       goto parse_failed;
1208
1209     if (str->samples[new_index].keyframe)
1210       break;
1211
1212     if (new_index == 0)
1213       break;
1214
1215     if (next)
1216       new_index++;
1217     else
1218       new_index--;
1219   }
1220
1221   if (new_index == str->n_samples) {
1222     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1223     new_index = -1;
1224   }
1225
1226 beach:
1227   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1228       "gave %u", next ? "after" : "before", index, new_index);
1229
1230   return new_index;
1231
1232   /* ERRORS */
1233 parse_failed:
1234   {
1235     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1236     return -1;
1237   }
1238 }
1239
1240 /* find the segment for @time_position for @stream
1241  *
1242  * Returns the index of the segment containing @time_position.
1243  * Returns the last segment and sets the @eos variable to TRUE
1244  * if the time is beyond the end. @eos may be NULL
1245  */
1246 static guint32
1247 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1248     GstClockTime time_position)
1249 {
1250   gint i;
1251   guint32 seg_idx;
1252
1253   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1254       GST_TIME_ARGS (time_position));
1255
1256   seg_idx = -1;
1257   for (i = 0; i < stream->n_segments; i++) {
1258     QtDemuxSegment *segment = &stream->segments[i];
1259
1260     GST_LOG_OBJECT (stream->pad,
1261         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1262         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1263
1264     /* For the last segment we include stop_time in the last segment */
1265     if (i < stream->n_segments - 1) {
1266       if (segment->time <= time_position && time_position < segment->stop_time) {
1267         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1268         seg_idx = i;
1269         break;
1270       }
1271     } else {
1272       /* Last segment always matches */
1273       seg_idx = i;
1274       break;
1275     }
1276   }
1277   return seg_idx;
1278 }
1279
1280 /* move the stream @str to the sample position @index.
1281  *
1282  * Updates @str->sample_index and marks discontinuity if needed.
1283  */
1284 static void
1285 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1286     guint32 index)
1287 {
1288   /* no change needed */
1289   if (index == str->sample_index)
1290     return;
1291
1292   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1293       str->n_samples);
1294
1295   /* position changed, we have a discont */
1296   str->sample_index = index;
1297   str->offset_in_sample = 0;
1298   /* Each time we move in the stream we store the position where we are
1299    * starting from */
1300   str->from_sample = index;
1301   str->discont = TRUE;
1302 }
1303
1304 static void
1305 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1306     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1307 {
1308   guint64 min_offset;
1309   gint64 min_byte_offset = -1;
1310   gint n;
1311
1312   min_offset = desired_time;
1313
1314   /* for each stream, find the index of the sample in the segment
1315    * and move back to the previous keyframe. */
1316   for (n = 0; n < qtdemux->n_streams; n++) {
1317     QtDemuxStream *str;
1318     guint32 index, kindex;
1319     guint32 seg_idx;
1320     GstClockTime media_start;
1321     GstClockTime media_time;
1322     GstClockTime seg_time;
1323     QtDemuxSegment *seg;
1324     gboolean empty_segment = FALSE;
1325
1326     str = qtdemux->streams[n];
1327
1328     if (CUR_STREAM (str)->sparse && !use_sparse)
1329       continue;
1330
1331     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1332     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1333
1334     /* get segment and time in the segment */
1335     seg = &str->segments[seg_idx];
1336     seg_time = (desired_time - seg->time) * seg->rate;
1337
1338     while (QTSEGMENT_IS_EMPTY (seg)) {
1339       seg_time = 0;
1340       empty_segment = TRUE;
1341       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1342           seg_idx);
1343       seg_idx++;
1344       if (seg_idx == str->n_segments)
1345         break;
1346       seg = &str->segments[seg_idx];
1347     }
1348
1349     if (seg_idx == str->n_segments) {
1350       /* FIXME track shouldn't have the last segment as empty, but if it
1351        * happens we better handle it */
1352       continue;
1353     }
1354
1355     /* get the media time in the segment */
1356     media_start = seg->media_start + seg_time;
1357
1358     /* get the index of the sample with media time */
1359     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1360     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1361         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1362         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1363         empty_segment);
1364
1365     /* shift to next frame if we are looking for next keyframe */
1366     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1367         && index < str->stbl_index)
1368       index++;
1369
1370     if (!empty_segment) {
1371       /* find previous keyframe */
1372       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1373
1374       /* we will settle for one before if none found after */
1375       if (next && kindex == -1)
1376         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1377
1378       /* if the keyframe is at a different position, we need to update the
1379        * requested seek time */
1380       if (index != kindex) {
1381         index = kindex;
1382
1383         /* get timestamp of keyframe */
1384         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1385         GST_DEBUG_OBJECT (qtdemux,
1386             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1387             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1388             str->samples[kindex].offset);
1389
1390         /* keyframes in the segment get a chance to change the
1391          * desired_offset. keyframes out of the segment are
1392          * ignored. */
1393         if (media_time >= seg->media_start) {
1394           GstClockTime seg_time;
1395
1396           /* this keyframe is inside the segment, convert back to
1397            * segment time */
1398           seg_time = (media_time - seg->media_start) + seg->time;
1399           if ((!next && (seg_time < min_offset)) ||
1400               (next && (seg_time > min_offset)))
1401             min_offset = seg_time;
1402         }
1403       }
1404     }
1405
1406     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1407       min_byte_offset = str->samples[index].offset;
1408   }
1409
1410   if (key_time)
1411     *key_time = min_offset;
1412   if (key_offset)
1413     *key_offset = min_byte_offset;
1414 }
1415
1416 static gboolean
1417 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1418     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1419 {
1420   gboolean res;
1421
1422   g_return_val_if_fail (format != NULL, FALSE);
1423   g_return_val_if_fail (cur != NULL, FALSE);
1424   g_return_val_if_fail (stop != NULL, FALSE);
1425
1426   if (*format == GST_FORMAT_TIME)
1427     return TRUE;
1428
1429   res = TRUE;
1430   if (cur_type != GST_SEEK_TYPE_NONE)
1431     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1432   if (res && stop_type != GST_SEEK_TYPE_NONE)
1433     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1434
1435   if (res)
1436     *format = GST_FORMAT_TIME;
1437
1438   return res;
1439 }
1440
1441 /* perform seek in push based mode:
1442    find BYTE position to move to based on time and delegate to upstream
1443 */
1444 static gboolean
1445 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1446 {
1447   gdouble rate;
1448   GstFormat format;
1449   GstSeekFlags flags;
1450   GstSeekType cur_type, stop_type;
1451   gint64 cur, stop, key_cur;
1452   gboolean res;
1453   gint64 byte_cur;
1454   gint64 original_stop;
1455   guint32 seqnum;
1456
1457   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1458
1459   gst_event_parse_seek (event, &rate, &format, &flags,
1460       &cur_type, &cur, &stop_type, &stop);
1461   seqnum = gst_event_get_seqnum (event);
1462
1463   /* only forward streaming and seeking is possible */
1464   if (rate <= 0)
1465     goto unsupported_seek;
1466
1467   /* convert to TIME if needed and possible */
1468   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1469           stop_type, &stop))
1470     goto no_format;
1471
1472   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1473    * the original stop position to use when upstream pushes the new segment
1474    * for this seek */
1475   original_stop = stop;
1476   stop = -1;
1477
1478   /* find reasonable corresponding BYTE position,
1479    * also try to mind about keyframes, since we can not go back a bit for them
1480    * later on */
1481   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1482    * mostly just work, but let's not yet boldly go there  ... */
1483   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1484
1485   if (byte_cur == -1)
1486     goto abort_seek;
1487
1488   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1489       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1490       stop);
1491
1492   GST_OBJECT_LOCK (qtdemux);
1493   qtdemux->seek_offset = byte_cur;
1494   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1495     qtdemux->push_seek_start = cur;
1496   } else {
1497     qtdemux->push_seek_start = key_cur;
1498   }
1499
1500   if (stop_type == GST_SEEK_TYPE_NONE) {
1501     qtdemux->push_seek_stop = qtdemux->segment.stop;
1502   } else {
1503     qtdemux->push_seek_stop = original_stop;
1504   }
1505   GST_OBJECT_UNLOCK (qtdemux);
1506
1507   /* BYTE seek event */
1508   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1509       stop_type, stop);
1510   gst_event_set_seqnum (event, seqnum);
1511   res = gst_pad_push_event (qtdemux->sinkpad, event);
1512
1513   return res;
1514
1515   /* ERRORS */
1516 abort_seek:
1517   {
1518     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1519         "seek aborted.");
1520     return FALSE;
1521   }
1522 unsupported_seek:
1523   {
1524     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1525     return FALSE;
1526   }
1527 no_format:
1528   {
1529     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1530     return FALSE;
1531   }
1532 }
1533
1534 /* perform the seek.
1535  *
1536  * We set all segment_indexes in the streams to unknown and
1537  * adjust the time_position to the desired position. this is enough
1538  * to trigger a segment switch in the streaming thread to start
1539  * streaming from the desired position.
1540  *
1541  * Keyframe seeking is a little more complicated when dealing with
1542  * segments. Ideally we want to move to the previous keyframe in
1543  * the segment but there might not be a keyframe in the segment. In
1544  * fact, none of the segments could contain a keyframe. We take a
1545  * practical approach: seek to the previous keyframe in the segment,
1546  * if there is none, seek to the beginning of the segment.
1547  *
1548  * Called with STREAM_LOCK
1549  */
1550 static gboolean
1551 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1552     guint32 seqnum, GstSeekFlags flags)
1553 {
1554   gint64 desired_offset;
1555   gint n;
1556
1557   desired_offset = segment->position;
1558
1559   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1560       GST_TIME_ARGS (desired_offset));
1561
1562   /* may not have enough fragmented info to do this adjustment,
1563    * and we can't scan (and probably should not) at this time with
1564    * possibly flushing upstream */
1565   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1566     gint64 min_offset;
1567     gboolean next, before, after;
1568
1569     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1570     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1571     next = after && !before;
1572     if (segment->rate < 0)
1573       next = !next;
1574
1575     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1576         NULL);
1577     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1578         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1579     desired_offset = min_offset;
1580   }
1581
1582   /* and set all streams to the final position */
1583   gst_flow_combiner_reset (qtdemux->flowcombiner);
1584   qtdemux->segment_seqnum = seqnum;
1585   for (n = 0; n < qtdemux->n_streams; n++) {
1586     QtDemuxStream *stream = qtdemux->streams[n];
1587
1588     stream->time_position = desired_offset;
1589     stream->accumulated_base = 0;
1590     stream->sample_index = -1;
1591     stream->offset_in_sample = 0;
1592     stream->segment_index = -1;
1593     stream->sent_eos = FALSE;
1594
1595     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1596       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1597   }
1598   segment->position = desired_offset;
1599   segment->time = desired_offset;
1600   if (segment->rate >= 0) {
1601     segment->start = desired_offset;
1602
1603     /* we stop at the end */
1604     if (segment->stop == -1)
1605       segment->stop = segment->duration;
1606   } else {
1607     segment->stop = desired_offset;
1608   }
1609
1610   if (qtdemux->fragmented)
1611     qtdemux->fragmented_seek_pending = TRUE;
1612
1613   return TRUE;
1614 }
1615
1616 /* do a seek in pull based mode */
1617 static gboolean
1618 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1619 {
1620   gdouble rate;
1621   GstFormat format;
1622   GstSeekFlags flags;
1623   GstSeekType cur_type, stop_type;
1624   gint64 cur, stop;
1625   gboolean flush;
1626   gboolean update;
1627   GstSegment seeksegment;
1628   guint32 seqnum = 0;
1629   GstEvent *flush_event;
1630
1631   if (event) {
1632     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1633
1634     gst_event_parse_seek (event, &rate, &format, &flags,
1635         &cur_type, &cur, &stop_type, &stop);
1636     seqnum = gst_event_get_seqnum (event);
1637
1638     /* we have to have a format as the segment format. Try to convert
1639      * if not. */
1640     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1641             stop_type, &stop))
1642       goto no_format;
1643
1644     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1645   } else {
1646     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1647     flags = 0;
1648   }
1649
1650   flush = flags & GST_SEEK_FLAG_FLUSH;
1651
1652   /* stop streaming, either by flushing or by pausing the task */
1653   if (flush) {
1654     flush_event = gst_event_new_flush_start ();
1655     if (seqnum)
1656       gst_event_set_seqnum (flush_event, seqnum);
1657     /* unlock upstream pull_range */
1658     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1659     /* make sure out loop function exits */
1660     gst_qtdemux_push_event (qtdemux, flush_event);
1661   } else {
1662     /* non flushing seek, pause the task */
1663     gst_pad_pause_task (qtdemux->sinkpad);
1664   }
1665
1666   /* wait for streaming to finish */
1667   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1668
1669   /* copy segment, we need this because we still need the old
1670    * segment when we close the current segment. */
1671   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1672
1673   if (event) {
1674     /* configure the segment with the seek variables */
1675     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1676     gst_segment_do_seek (&seeksegment, rate, format, flags,
1677         cur_type, cur, stop_type, stop, &update);
1678   }
1679
1680   /* now do the seek, this actually never returns FALSE */
1681   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1682
1683   /* prepare for streaming again */
1684   if (flush) {
1685     flush_event = gst_event_new_flush_stop (TRUE);
1686     if (seqnum)
1687       gst_event_set_seqnum (flush_event, seqnum);
1688
1689     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1690     gst_qtdemux_push_event (qtdemux, flush_event);
1691   }
1692
1693   /* commit the new segment */
1694   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1695
1696   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1697     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1698         qtdemux->segment.format, qtdemux->segment.position);
1699     if (seqnum)
1700       gst_message_set_seqnum (msg, seqnum);
1701     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1702   }
1703
1704   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1705   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1706       qtdemux->sinkpad, NULL);
1707
1708   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1709
1710   return TRUE;
1711
1712   /* ERRORS */
1713 no_format:
1714   {
1715     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1716     return FALSE;
1717   }
1718 }
1719
1720 static gboolean
1721 qtdemux_ensure_index (GstQTDemux * qtdemux)
1722 {
1723   guint i;
1724
1725   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1726
1727   /* Build complete index */
1728   for (i = 0; i < qtdemux->n_streams; i++) {
1729     QtDemuxStream *stream = qtdemux->streams[i];
1730
1731     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1732       goto parse_error;
1733   }
1734   return TRUE;
1735
1736   /* ERRORS */
1737 parse_error:
1738   {
1739     GST_LOG_OBJECT (qtdemux,
1740         "Building complete index of stream %u for seeking failed!", i);
1741     return FALSE;
1742   }
1743 }
1744
1745 static gboolean
1746 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1747     GstEvent * event)
1748 {
1749   gboolean res = TRUE;
1750   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1751
1752   switch (GST_EVENT_TYPE (event)) {
1753     case GST_EVENT_SEEK:
1754     {
1755 #ifndef GST_DISABLE_GST_DEBUG
1756       GstClockTime ts = gst_util_get_timestamp ();
1757 #endif
1758       guint32 seqnum = gst_event_get_seqnum (event);
1759
1760       if (seqnum == qtdemux->segment_seqnum) {
1761         GST_LOG_OBJECT (pad,
1762             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1763         gst_event_unref (event);
1764         return TRUE;
1765       }
1766
1767       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1768         /* seek should be handled by upstream, we might need to re-download fragments */
1769         GST_DEBUG_OBJECT (qtdemux,
1770             "let upstream handle seek for fragmented playback");
1771         goto upstream;
1772       }
1773
1774       /* Build complete index for seeking;
1775        * if not a fragmented file at least */
1776       if (!qtdemux->fragmented)
1777         if (!qtdemux_ensure_index (qtdemux))
1778           goto index_failed;
1779 #ifndef GST_DISABLE_GST_DEBUG
1780       ts = gst_util_get_timestamp () - ts;
1781       GST_INFO_OBJECT (qtdemux,
1782           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1783 #endif
1784     }
1785       if (qtdemux->pullbased) {
1786         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1787       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1788         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1789         res = TRUE;
1790       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1791           && !qtdemux->fragmented) {
1792         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1793       } else {
1794         GST_DEBUG_OBJECT (qtdemux,
1795             "ignoring seek in push mode in current state");
1796         res = FALSE;
1797       }
1798       gst_event_unref (event);
1799       break;
1800     default:
1801     upstream:
1802       res = gst_pad_event_default (pad, parent, event);
1803       break;
1804   }
1805
1806 done:
1807   return res;
1808
1809   /* ERRORS */
1810 index_failed:
1811   {
1812     GST_ERROR_OBJECT (qtdemux, "Index failed");
1813     gst_event_unref (event);
1814     res = FALSE;
1815     goto done;
1816   }
1817 }
1818
1819 /* stream/index return sample that is min/max w.r.t. byte position,
1820  * time is min/max w.r.t. time of samples,
1821  * the latter need not be time of the former sample */
1822 static void
1823 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1824     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1825 {
1826   gint i, n, index;
1827   gint64 time, min_time;
1828   QtDemuxStream *stream;
1829
1830   min_time = -1;
1831   stream = NULL;
1832   index = -1;
1833
1834   for (n = 0; n < qtdemux->n_streams; ++n) {
1835     QtDemuxStream *str;
1836     gint inc;
1837     gboolean set_sample;
1838
1839     str = qtdemux->streams[n];
1840     set_sample = !set;
1841
1842     if (fw) {
1843       i = 0;
1844       inc = 1;
1845     } else {
1846       i = str->n_samples - 1;
1847       inc = -1;
1848     }
1849
1850     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1851       if (str->samples[i].size == 0)
1852         continue;
1853
1854       if (fw && (str->samples[i].offset < byte_pos))
1855         continue;
1856
1857       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1858         continue;
1859
1860       /* move stream to first available sample */
1861       if (set) {
1862         gst_qtdemux_move_stream (qtdemux, str, i);
1863         set_sample = TRUE;
1864       }
1865
1866       /* avoid index from sparse streams since they might be far away */
1867       if (!CUR_STREAM (str)->sparse) {
1868         /* determine min/max time */
1869         time = QTSAMPLE_PTS (str, &str->samples[i]);
1870         if (min_time == -1 || (!fw && time > min_time) ||
1871             (fw && time < min_time)) {
1872           min_time = time;
1873         }
1874
1875         /* determine stream with leading sample, to get its position */
1876         if (!stream ||
1877             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1878             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1879           stream = str;
1880           index = i;
1881         }
1882       }
1883       break;
1884     }
1885
1886     /* no sample for this stream, mark eos */
1887     if (!set_sample)
1888       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1889   }
1890
1891   if (_time)
1892     *_time = min_time;
1893   if (_stream)
1894     *_stream = stream;
1895   if (_index)
1896     *_index = index;
1897 }
1898
1899 static QtDemuxStream *
1900 _create_stream (void)
1901 {
1902   QtDemuxStream *stream;
1903
1904   stream = g_new0 (QtDemuxStream, 1);
1905   /* new streams always need a discont */
1906   stream->discont = TRUE;
1907   /* we enable clipping for raw audio/video streams */
1908   stream->need_clip = FALSE;
1909   stream->need_process = FALSE;
1910   stream->segment_index = -1;
1911   stream->time_position = 0;
1912   stream->sample_index = -1;
1913   stream->offset_in_sample = 0;
1914   stream->new_stream = TRUE;
1915   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1916   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1917   stream->protected = FALSE;
1918   stream->protection_scheme_type = 0;
1919   stream->protection_scheme_version = 0;
1920   stream->protection_scheme_info = NULL;
1921   stream->n_samples_moof = 0;
1922   stream->duration_moof = 0;
1923   stream->duration_last_moof = 0;
1924   stream->alignment = 1;
1925   stream->stream_tags = gst_tag_list_new_empty ();
1926   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1927   g_queue_init (&stream->protection_scheme_event_queue);
1928   return stream;
1929 }
1930
1931 static gboolean
1932 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1933 {
1934   GstStructure *structure;
1935   const gchar *variant;
1936   const GstCaps *mediacaps = NULL;
1937
1938   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1939
1940   structure = gst_caps_get_structure (caps, 0);
1941   variant = gst_structure_get_string (structure, "variant");
1942
1943   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1944     QtDemuxStream *stream;
1945     const GValue *value;
1946
1947     demux->fragmented = TRUE;
1948     demux->mss_mode = TRUE;
1949
1950     if (demux->n_streams > 1) {
1951       /* can't do this, we can only renegotiate for another mss format */
1952       return FALSE;
1953     }
1954
1955     value = gst_structure_get_value (structure, "media-caps");
1956     /* create stream */
1957     if (value) {
1958       const GValue *timescale_v;
1959
1960       /* TODO update when stream changes during playback */
1961
1962       if (demux->n_streams == 0) {
1963         stream = _create_stream ();
1964         demux->streams[demux->n_streams] = stream;
1965         demux->n_streams = 1;
1966       } else {
1967         stream = demux->streams[0];
1968       }
1969
1970       timescale_v = gst_structure_get_value (structure, "timescale");
1971       if (timescale_v) {
1972         stream->timescale = g_value_get_uint64 (timescale_v);
1973       } else {
1974         /* default mss timescale */
1975         stream->timescale = 10000000;
1976       }
1977       demux->timescale = stream->timescale;
1978
1979       mediacaps = gst_value_get_caps (value);
1980       if (!CUR_STREAM (stream)->caps
1981           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1982         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1983             mediacaps);
1984         stream->new_caps = TRUE;
1985       }
1986       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1987       structure = gst_caps_get_structure (mediacaps, 0);
1988       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1989         stream->subtype = FOURCC_vide;
1990
1991         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1992         gst_structure_get_int (structure, "height",
1993             &CUR_STREAM (stream)->height);
1994         gst_structure_get_fraction (structure, "framerate",
1995             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1996       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1997         gint rate = 0;
1998         stream->subtype = FOURCC_soun;
1999         gst_structure_get_int (structure, "channels",
2000             &CUR_STREAM (stream)->n_channels);
2001         gst_structure_get_int (structure, "rate", &rate);
2002         CUR_STREAM (stream)->rate = rate;
2003       }
2004     }
2005     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2006   } else {
2007     demux->mss_mode = FALSE;
2008   }
2009
2010   return TRUE;
2011 }
2012
2013 static void
2014 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2015 {
2016   gint n;
2017
2018   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2019   gst_pad_stop_task (qtdemux->sinkpad);
2020
2021   if (hard || qtdemux->upstream_format_is_time) {
2022     qtdemux->state = QTDEMUX_STATE_INITIAL;
2023     qtdemux->neededbytes = 16;
2024     qtdemux->todrop = 0;
2025     qtdemux->pullbased = FALSE;
2026     qtdemux->posted_redirect = FALSE;
2027     qtdemux->first_mdat = -1;
2028     qtdemux->header_size = 0;
2029     qtdemux->mdatoffset = -1;
2030     qtdemux->restoredata_offset = -1;
2031     if (qtdemux->mdatbuffer)
2032       gst_buffer_unref (qtdemux->mdatbuffer);
2033     if (qtdemux->restoredata_buffer)
2034       gst_buffer_unref (qtdemux->restoredata_buffer);
2035     qtdemux->mdatbuffer = NULL;
2036     qtdemux->restoredata_buffer = NULL;
2037     qtdemux->mdatleft = 0;
2038     qtdemux->mdatsize = 0;
2039     if (qtdemux->comp_brands)
2040       gst_buffer_unref (qtdemux->comp_brands);
2041     qtdemux->comp_brands = NULL;
2042     qtdemux->last_moov_offset = -1;
2043     if (qtdemux->moov_node_compressed) {
2044       g_node_destroy (qtdemux->moov_node_compressed);
2045       if (qtdemux->moov_node)
2046         g_free (qtdemux->moov_node->data);
2047     }
2048     qtdemux->moov_node_compressed = NULL;
2049     if (qtdemux->moov_node)
2050       g_node_destroy (qtdemux->moov_node);
2051     qtdemux->moov_node = NULL;
2052     if (qtdemux->tag_list)
2053       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2054     qtdemux->tag_list = gst_tag_list_new_empty ();
2055     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2056 #if 0
2057     if (qtdemux->element_index)
2058       gst_object_unref (qtdemux->element_index);
2059     qtdemux->element_index = NULL;
2060 #endif
2061     qtdemux->major_brand = 0;
2062     if (qtdemux->pending_newsegment)
2063       gst_event_unref (qtdemux->pending_newsegment);
2064     qtdemux->pending_newsegment = NULL;
2065     qtdemux->upstream_format_is_time = FALSE;
2066     qtdemux->upstream_seekable = FALSE;
2067     qtdemux->upstream_size = 0;
2068
2069     qtdemux->fragment_start = -1;
2070     qtdemux->fragment_start_offset = -1;
2071     qtdemux->duration = 0;
2072     qtdemux->moof_offset = 0;
2073     qtdemux->chapters_track_id = 0;
2074     qtdemux->have_group_id = FALSE;
2075     qtdemux->group_id = G_MAXUINT;
2076
2077     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2078         NULL);
2079     g_queue_clear (&qtdemux->protection_event_queue);
2080   }
2081   qtdemux->offset = 0;
2082   gst_adapter_clear (qtdemux->adapter);
2083   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2084   qtdemux->segment_seqnum = 0;
2085
2086   if (hard) {
2087     for (n = 0; n < qtdemux->n_streams; n++) {
2088       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2089       qtdemux->streams[n] = NULL;
2090     }
2091     qtdemux->n_streams = 0;
2092     qtdemux->n_video_streams = 0;
2093     qtdemux->n_audio_streams = 0;
2094     qtdemux->n_sub_streams = 0;
2095     qtdemux->exposed = FALSE;
2096     qtdemux->fragmented = FALSE;
2097     qtdemux->mss_mode = FALSE;
2098     gst_caps_replace (&qtdemux->media_caps, NULL);
2099     qtdemux->timescale = 0;
2100     qtdemux->got_moov = FALSE;
2101     if (qtdemux->protection_system_ids) {
2102       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2103       qtdemux->protection_system_ids = NULL;
2104     }
2105   } else if (qtdemux->mss_mode) {
2106     gst_flow_combiner_reset (qtdemux->flowcombiner);
2107     for (n = 0; n < qtdemux->n_streams; n++)
2108       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2109   } else {
2110     gst_flow_combiner_reset (qtdemux->flowcombiner);
2111     for (n = 0; n < qtdemux->n_streams; n++) {
2112       qtdemux->streams[n]->sent_eos = FALSE;
2113       qtdemux->streams[n]->time_position = 0;
2114       qtdemux->streams[n]->accumulated_base = 0;
2115     }
2116     if (!qtdemux->pending_newsegment) {
2117       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2118       if (qtdemux->segment_seqnum)
2119         gst_event_set_seqnum (qtdemux->pending_newsegment,
2120             qtdemux->segment_seqnum);
2121     }
2122   }
2123 }
2124
2125
2126 /* Maps the @segment to the qt edts internal segments and pushes
2127  * the correspnding segment event.
2128  *
2129  * If it ends up being at a empty segment, a gap will be pushed and the next
2130  * edts segment will be activated in sequence.
2131  *
2132  * To be used in push-mode only */
2133 static void
2134 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2135 {
2136   gint n, i;
2137
2138   for (n = 0; n < qtdemux->n_streams; n++) {
2139     QtDemuxStream *stream = qtdemux->streams[n];
2140
2141     stream->time_position = segment->start;
2142
2143     /* in push mode we should be guaranteed that we will have empty segments
2144      * at the beginning and then one segment after, other scenarios are not
2145      * supported and are discarded when parsing the edts */
2146     for (i = 0; i < stream->n_segments; i++) {
2147       if (stream->segments[i].stop_time > segment->start) {
2148         gst_qtdemux_activate_segment (qtdemux, stream, i,
2149             stream->time_position);
2150         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2151           /* push the empty segment and move to the next one */
2152           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2153               stream->time_position);
2154           continue;
2155         }
2156
2157         g_assert (i == stream->n_segments - 1);
2158       }
2159     }
2160   }
2161 }
2162
2163 static gboolean
2164 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2165     GstEvent * event)
2166 {
2167   GstQTDemux *demux = GST_QTDEMUX (parent);
2168   gboolean res = TRUE;
2169
2170   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2171
2172   switch (GST_EVENT_TYPE (event)) {
2173     case GST_EVENT_SEGMENT:
2174     {
2175       gint64 offset = 0;
2176       QtDemuxStream *stream;
2177       gint idx;
2178       GstSegment segment;
2179
2180       /* some debug output */
2181       gst_event_copy_segment (event, &segment);
2182       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2183           &segment);
2184
2185       /* erase any previously set segment */
2186       gst_event_replace (&demux->pending_newsegment, NULL);
2187
2188       if (segment.format == GST_FORMAT_TIME) {
2189         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2190         gst_event_replace (&demux->pending_newsegment, event);
2191         demux->upstream_format_is_time = TRUE;
2192       } else {
2193         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2194             "not in time format");
2195
2196         /* chain will send initial newsegment after pads have been added */
2197         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2198           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2199           goto exit;
2200         }
2201       }
2202
2203       /* check if this matches a time seek we received previously
2204        * FIXME for backwards compatibility reasons we use the
2205        * seek_offset here to compare. In the future we might want to
2206        * change this to use the seqnum as it uniquely should identify
2207        * the segment that corresponds to the seek. */
2208       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2209           ", received segment offset %" G_GINT64_FORMAT,
2210           demux->seek_offset, segment.start);
2211       if (segment.format == GST_FORMAT_BYTES
2212           && demux->seek_offset == segment.start) {
2213         GST_OBJECT_LOCK (demux);
2214         offset = segment.start;
2215
2216         segment.format = GST_FORMAT_TIME;
2217         segment.start = demux->push_seek_start;
2218         segment.stop = demux->push_seek_stop;
2219         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2220             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2221             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2222         GST_OBJECT_UNLOCK (demux);
2223       }
2224
2225       /* we only expect a BYTE segment, e.g. following a seek */
2226       if (segment.format == GST_FORMAT_BYTES) {
2227         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2228           offset = segment.start;
2229
2230           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2231               NULL, (gint64 *) & segment.start);
2232           if ((gint64) segment.start < 0)
2233             segment.start = 0;
2234         }
2235         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2236           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2237               NULL, (gint64 *) & segment.stop);
2238           /* keyframe seeking should already arrange for start >= stop,
2239            * but make sure in other rare cases */
2240           segment.stop = MAX (segment.stop, segment.start);
2241         }
2242       } else if (segment.format == GST_FORMAT_TIME) {
2243         /* push all data on the adapter before starting this
2244          * new segment */
2245         gst_qtdemux_process_adapter (demux, TRUE);
2246       } else {
2247         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2248         goto exit;
2249       }
2250
2251       /* We shouldn't modify upstream driven TIME FORMAT segment */
2252       if (!demux->upstream_format_is_time) {
2253         /* accept upstream's notion of segment and distribute along */
2254         segment.format = GST_FORMAT_TIME;
2255         segment.position = segment.time = segment.start;
2256         segment.duration = demux->segment.duration;
2257         segment.base = gst_segment_to_running_time (&demux->segment,
2258             GST_FORMAT_TIME, demux->segment.position);
2259       }
2260
2261       gst_segment_copy_into (&segment, &demux->segment);
2262       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2263
2264       /* map segment to internal qt segments and push on each stream */
2265       if (demux->n_streams) {
2266         if (demux->fragmented) {
2267           GstEvent *segment_event = gst_event_new_segment (&segment);
2268
2269           gst_event_replace (&demux->pending_newsegment, NULL);
2270           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2271           gst_qtdemux_push_event (demux, segment_event);
2272         } else {
2273           gst_event_replace (&demux->pending_newsegment, NULL);
2274           gst_qtdemux_map_and_push_segments (demux, &segment);
2275         }
2276       }
2277
2278       /* clear leftover in current segment, if any */
2279       gst_adapter_clear (demux->adapter);
2280
2281       /* set up streaming thread */
2282       demux->offset = offset;
2283       if (demux->upstream_format_is_time) {
2284         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2285             "set values to restart reading from a new atom");
2286         demux->neededbytes = 16;
2287         demux->todrop = 0;
2288       } else {
2289         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2290             NULL);
2291         if (stream) {
2292           demux->todrop = stream->samples[idx].offset - offset;
2293           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2294         } else {
2295           /* set up for EOS */
2296           demux->neededbytes = -1;
2297           demux->todrop = 0;
2298         }
2299       }
2300     exit:
2301       gst_event_unref (event);
2302       res = TRUE;
2303       goto drop;
2304     }
2305     case GST_EVENT_FLUSH_START:
2306     {
2307       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2308         gst_event_unref (event);
2309         goto drop;
2310       }
2311       break;
2312     }
2313     case GST_EVENT_FLUSH_STOP:
2314     {
2315       guint64 dur;
2316
2317       dur = demux->segment.duration;
2318       gst_qtdemux_reset (demux, FALSE);
2319       demux->segment.duration = dur;
2320
2321       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2322         gst_event_unref (event);
2323         goto drop;
2324       }
2325       break;
2326     }
2327     case GST_EVENT_EOS:
2328       /* If we are in push mode, and get an EOS before we've seen any streams,
2329        * then error out - we have nowhere to send the EOS */
2330       if (!demux->pullbased) {
2331         gint i;
2332         gboolean has_valid_stream = FALSE;
2333         for (i = 0; i < demux->n_streams; i++) {
2334           if (demux->streams[i]->pad != NULL) {
2335             has_valid_stream = TRUE;
2336             break;
2337           }
2338         }
2339         if (!has_valid_stream)
2340           gst_qtdemux_post_no_playable_stream_error (demux);
2341         else {
2342           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2343               (guint) gst_adapter_available (demux->adapter));
2344           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2345             res = FALSE;
2346           }
2347         }
2348       }
2349       break;
2350     case GST_EVENT_CAPS:{
2351       GstCaps *caps = NULL;
2352
2353       gst_event_parse_caps (event, &caps);
2354       gst_qtdemux_setcaps (demux, caps);
2355       res = TRUE;
2356       gst_event_unref (event);
2357       goto drop;
2358     }
2359     case GST_EVENT_PROTECTION:
2360     {
2361       const gchar *system_id = NULL;
2362
2363       gst_event_parse_protection (event, &system_id, NULL, NULL);
2364       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2365           system_id);
2366       gst_qtdemux_append_protection_system_id (demux, system_id);
2367       /* save the event for later, for source pads that have not been created */
2368       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2369       /* send it to all pads that already exist */
2370       gst_qtdemux_push_event (demux, event);
2371       res = TRUE;
2372       goto drop;
2373     }
2374     default:
2375       break;
2376   }
2377
2378   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2379
2380 drop:
2381   return res;
2382 }
2383
2384 #if 0
2385 static void
2386 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2387 {
2388   GstQTDemux *demux = GST_QTDEMUX (element);
2389
2390   GST_OBJECT_LOCK (demux);
2391   if (demux->element_index)
2392     gst_object_unref (demux->element_index);
2393   if (index) {
2394     demux->element_index = gst_object_ref (index);
2395   } else {
2396     demux->element_index = NULL;
2397   }
2398   GST_OBJECT_UNLOCK (demux);
2399   /* object lock might be taken again */
2400   if (index)
2401     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2402   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2403       demux->element_index, demux->index_id);
2404 }
2405
2406 static GstIndex *
2407 gst_qtdemux_get_index (GstElement * element)
2408 {
2409   GstIndex *result = NULL;
2410   GstQTDemux *demux = GST_QTDEMUX (element);
2411
2412   GST_OBJECT_LOCK (demux);
2413   if (demux->element_index)
2414     result = gst_object_ref (demux->element_index);
2415   GST_OBJECT_UNLOCK (demux);
2416
2417   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2418
2419   return result;
2420 }
2421 #endif
2422
2423 static void
2424 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2425 {
2426   g_free ((gpointer) stream->stco.data);
2427   stream->stco.data = NULL;
2428   g_free ((gpointer) stream->stsz.data);
2429   stream->stsz.data = NULL;
2430   g_free ((gpointer) stream->stsc.data);
2431   stream->stsc.data = NULL;
2432   g_free ((gpointer) stream->stts.data);
2433   stream->stts.data = NULL;
2434   g_free ((gpointer) stream->stss.data);
2435   stream->stss.data = NULL;
2436   g_free ((gpointer) stream->stps.data);
2437   stream->stps.data = NULL;
2438   g_free ((gpointer) stream->ctts.data);
2439   stream->ctts.data = NULL;
2440 }
2441
2442 static void
2443 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2444     QtDemuxStream * stream)
2445 {
2446   g_free (stream->segments);
2447   stream->segments = NULL;
2448   stream->segment_index = -1;
2449   stream->accumulated_base = 0;
2450 }
2451
2452 static void
2453 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2454     QtDemuxStream * stream)
2455 {
2456   g_free (stream->samples);
2457   stream->samples = NULL;
2458   gst_qtdemux_stbl_free (stream);
2459
2460   /* fragments */
2461   g_free (stream->ra_entries);
2462   stream->ra_entries = NULL;
2463   stream->n_ra_entries = 0;
2464
2465   stream->sample_index = -1;
2466   stream->stbl_index = -1;
2467   stream->n_samples = 0;
2468   stream->time_position = 0;
2469
2470   stream->n_samples_moof = 0;
2471   stream->duration_moof = 0;
2472   stream->duration_last_moof = 0;
2473 }
2474
2475 static void
2476 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2477 {
2478   gint i;
2479   if (stream->allocator)
2480     gst_object_unref (stream->allocator);
2481   while (stream->buffers) {
2482     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2483     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2484   }
2485   for (i = 0; i < stream->stsd_entries_length; i++) {
2486     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2487     if (entry->rgb8_palette) {
2488       gst_memory_unref (entry->rgb8_palette);
2489       entry->rgb8_palette = NULL;
2490     }
2491     entry->sparse = FALSE;
2492   }
2493
2494   gst_tag_list_unref (stream->stream_tags);
2495   stream->stream_tags = gst_tag_list_new_empty ();
2496   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2497   g_free (stream->redirect_uri);
2498   stream->redirect_uri = NULL;
2499   stream->sent_eos = FALSE;
2500   stream->protected = FALSE;
2501   if (stream->protection_scheme_info) {
2502     if (stream->protection_scheme_type == FOURCC_cenc) {
2503       QtDemuxCencSampleSetInfo *info =
2504           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2505       if (info->default_properties)
2506         gst_structure_free (info->default_properties);
2507       if (info->crypto_info)
2508         g_ptr_array_free (info->crypto_info, TRUE);
2509     }
2510     g_free (stream->protection_scheme_info);
2511     stream->protection_scheme_info = NULL;
2512   }
2513   stream->protection_scheme_type = 0;
2514   stream->protection_scheme_version = 0;
2515   g_queue_foreach (&stream->protection_scheme_event_queue,
2516       (GFunc) gst_event_unref, NULL);
2517   g_queue_clear (&stream->protection_scheme_event_queue);
2518   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2519   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2520 }
2521
2522 static void
2523 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2524 {
2525   gint i;
2526   gst_qtdemux_stream_clear (qtdemux, stream);
2527   for (i = 0; i < stream->stsd_entries_length; i++) {
2528     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2529     if (entry->caps) {
2530       gst_caps_unref (entry->caps);
2531       entry->caps = NULL;
2532     }
2533   }
2534   gst_tag_list_unref (stream->stream_tags);
2535   if (stream->pad) {
2536     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2537     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2538   }
2539   g_free (stream);
2540 }
2541
2542 static void
2543 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2544 {
2545   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2546
2547   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2548   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2549   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2550   qtdemux->n_streams--;
2551 }
2552
2553 static GstStateChangeReturn
2554 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2555 {
2556   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2557   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2558
2559   switch (transition) {
2560     case GST_STATE_CHANGE_PAUSED_TO_READY:
2561       break;
2562     default:
2563       break;
2564   }
2565
2566   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2567
2568   switch (transition) {
2569     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2570       gst_qtdemux_reset (qtdemux, TRUE);
2571       break;
2572     }
2573     default:
2574       break;
2575   }
2576
2577   return result;
2578 }
2579
2580 static void
2581 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2582 {
2583   /* counts as header data */
2584   qtdemux->header_size += length;
2585
2586   /* only consider at least a sufficiently complete ftyp atom */
2587   if (length >= 20) {
2588     GstBuffer *buf;
2589
2590     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2591     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2592         GST_FOURCC_ARGS (qtdemux->major_brand));
2593     if (qtdemux->comp_brands)
2594       gst_buffer_unref (qtdemux->comp_brands);
2595     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2596     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2597   }
2598 }
2599
2600 static void
2601 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2602     GstTagList * xmptaglist)
2603 {
2604   /* Strip out bogus fields */
2605   if (xmptaglist) {
2606     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2607       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2608       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2609     } else {
2610       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2611     }
2612
2613     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2614
2615     /* prioritize native tags using _KEEP mode */
2616     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2617     gst_tag_list_unref (xmptaglist);
2618   }
2619 }
2620
2621 static void
2622 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2623     guint offset)
2624 {
2625   GstByteReader br;
2626   guint8 version;
2627   guint32 flags = 0;
2628   guint i;
2629   guint8 iv_size = 8;
2630   QtDemuxStream *stream;
2631   GstStructure *structure;
2632   QtDemuxCencSampleSetInfo *ss_info = NULL;
2633   const gchar *system_id;
2634   gboolean uses_sub_sample_encryption = FALSE;
2635
2636   if (qtdemux->n_streams == 0)
2637     return;
2638
2639   stream = qtdemux->streams[0];
2640
2641   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2642   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2643     GST_WARNING_OBJECT (qtdemux,
2644         "Attempting PIFF box parsing on an unencrypted stream.");
2645     return;
2646   }
2647
2648   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2649       G_TYPE_STRING, &system_id, NULL);
2650   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2651
2652   stream->protected = TRUE;
2653   stream->protection_scheme_type = FOURCC_cenc;
2654
2655   if (!stream->protection_scheme_info)
2656     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2657
2658   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2659
2660   if (ss_info->default_properties)
2661     gst_structure_free (ss_info->default_properties);
2662
2663   ss_info->default_properties =
2664       gst_structure_new ("application/x-cenc",
2665       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2666
2667   if (ss_info->crypto_info) {
2668     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2669     g_ptr_array_free (ss_info->crypto_info, TRUE);
2670     ss_info->crypto_info = NULL;
2671   }
2672
2673   /* skip UUID */
2674   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2675
2676   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2677     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2678     return;
2679   }
2680
2681   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2682     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2683     return;
2684   }
2685
2686   if ((flags & 0x000001)) {
2687     guint32 algorithm_id = 0;
2688     const guint8 *kid;
2689     GstBuffer *kid_buf;
2690     gboolean is_encrypted = TRUE;
2691
2692     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2693       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2694       return;
2695     }
2696
2697     algorithm_id >>= 8;
2698     if (algorithm_id == 0) {
2699       is_encrypted = FALSE;
2700     } else if (algorithm_id == 1) {
2701       /* FIXME: maybe store this in properties? */
2702       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2703     } else if (algorithm_id == 2) {
2704       /* FIXME: maybe store this in properties? */
2705       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2706     }
2707
2708     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2709       return;
2710
2711     if (!gst_byte_reader_get_data (&br, 16, &kid))
2712       return;
2713
2714     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2715     gst_buffer_fill (kid_buf, 0, kid, 16);
2716     if (ss_info->default_properties)
2717       gst_structure_free (ss_info->default_properties);
2718     ss_info->default_properties =
2719         gst_structure_new ("application/x-cenc",
2720         "iv_size", G_TYPE_UINT, iv_size,
2721         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2722         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2723     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2724         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2725     gst_buffer_unref (kid_buf);
2726   } else if ((flags & 0x000002)) {
2727     uses_sub_sample_encryption = TRUE;
2728   }
2729
2730   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2731     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2732     return;
2733   }
2734
2735   ss_info->crypto_info =
2736       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2737       (GDestroyNotify) qtdemux_gst_structure_free);
2738
2739   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2740     GstStructure *properties;
2741     guint8 *data;
2742     GstBuffer *buf;
2743
2744     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2745     if (properties == NULL) {
2746       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2747       return;
2748     }
2749
2750     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2751       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2752       gst_structure_free (properties);
2753       return;
2754     }
2755     buf = gst_buffer_new_wrapped (data, iv_size);
2756     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2757     gst_buffer_unref (buf);
2758
2759     if (uses_sub_sample_encryption) {
2760       guint16 n_subsamples;
2761
2762       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2763           || n_subsamples == 0) {
2764         GST_ERROR_OBJECT (qtdemux,
2765             "failed to get subsample count for sample %u", i);
2766         gst_structure_free (properties);
2767         return;
2768       }
2769       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2770       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2771         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2772             i);
2773         gst_structure_free (properties);
2774         return;
2775       }
2776       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2777       gst_structure_set (properties,
2778           "subsample_count", G_TYPE_UINT, n_subsamples,
2779           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2780       gst_buffer_unref (buf);
2781     } else {
2782       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2783     }
2784
2785     g_ptr_array_add (ss_info->crypto_info, properties);
2786   }
2787 }
2788
2789 static void
2790 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2791 {
2792   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2793     0x97, 0xA9, 0x42, 0xE8,
2794     0x9C, 0x71, 0x99, 0x94,
2795     0x91, 0xE3, 0xAF, 0xAC
2796   };
2797   static const guint8 playready_uuid[] = {
2798     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2799     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2800   };
2801
2802   static const guint8 piff_sample_encryption_uuid[] = {
2803     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2804     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2805   };
2806
2807   guint offset;
2808
2809   /* counts as header data */
2810   qtdemux->header_size += length;
2811
2812   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2813
2814   if (length <= offset + 16) {
2815     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2816     return;
2817   }
2818
2819   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2820     GstBuffer *buf;
2821     GstTagList *taglist;
2822
2823     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2824         length - offset - 16, NULL);
2825     taglist = gst_tag_list_from_xmp_buffer (buf);
2826     gst_buffer_unref (buf);
2827
2828     /* make sure we have a usable taglist */
2829     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2830
2831     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2832
2833   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2834     int len;
2835     const gunichar2 *s_utf16;
2836     char *contents;
2837
2838     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2839     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2840     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2841     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2842
2843     g_free (contents);
2844
2845     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2846         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2847         (NULL));
2848   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2849     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2850   } else {
2851     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2852         GST_READ_UINT32_LE (buffer + offset),
2853         GST_READ_UINT32_LE (buffer + offset + 4),
2854         GST_READ_UINT32_LE (buffer + offset + 8),
2855         GST_READ_UINT32_LE (buffer + offset + 12));
2856   }
2857 }
2858
2859 static void
2860 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2861 {
2862   GstSidxParser sidx_parser;
2863   GstIsoffParserResult res;
2864   guint consumed;
2865
2866   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2867
2868   res =
2869       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2870       &consumed);
2871   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2872   if (res == GST_ISOFF_QT_PARSER_DONE) {
2873     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2874   }
2875   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2876 }
2877
2878 /* caller verifies at least 8 bytes in buf */
2879 static void
2880 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2881     guint64 * plength, guint32 * pfourcc)
2882 {
2883   guint64 length;
2884   guint32 fourcc;
2885
2886   length = QT_UINT32 (data);
2887   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2888   fourcc = QT_FOURCC (data + 4);
2889   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2890
2891   if (length == 0) {
2892     length = G_MAXUINT64;
2893   } else if (length == 1 && size >= 16) {
2894     /* this means we have an extended size, which is the 64 bit value of
2895      * the next 8 bytes */
2896     length = QT_UINT64 (data + 8);
2897     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2898   }
2899
2900   if (plength)
2901     *plength = length;
2902   if (pfourcc)
2903     *pfourcc = fourcc;
2904 }
2905
2906 static gboolean
2907 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2908 {
2909   guint32 version = 0;
2910   GstClockTime duration = 0;
2911
2912   if (!gst_byte_reader_get_uint32_be (br, &version))
2913     goto failed;
2914
2915   version >>= 24;
2916   if (version == 1) {
2917     if (!gst_byte_reader_get_uint64_be (br, &duration))
2918       goto failed;
2919   } else {
2920     guint32 dur = 0;
2921
2922     if (!gst_byte_reader_get_uint32_be (br, &dur))
2923       goto failed;
2924     duration = dur;
2925   }
2926
2927   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2928   qtdemux->duration = duration;
2929
2930   return TRUE;
2931
2932 failed:
2933   {
2934     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2935     return FALSE;
2936   }
2937 }
2938
2939 static gboolean
2940 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2941     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2942 {
2943   if (!stream->parsed_trex && qtdemux->moov_node) {
2944     GNode *mvex, *trex;
2945     GstByteReader trex_data;
2946
2947     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2948     if (mvex) {
2949       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2950           &trex_data);
2951       while (trex) {
2952         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2953
2954         /* skip version/flags */
2955         if (!gst_byte_reader_skip (&trex_data, 4))
2956           goto next;
2957         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2958           goto next;
2959         if (id != stream->track_id)
2960           goto next;
2961         /* sample description index; ignore */
2962         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2963           goto next;
2964         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2965           goto next;
2966         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2967           goto next;
2968         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2969           goto next;
2970
2971         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2972             "duration %d,  size %d, flags 0x%x", stream->track_id,
2973             dur, size, flags);
2974
2975         stream->parsed_trex = TRUE;
2976         stream->def_sample_duration = dur;
2977         stream->def_sample_size = size;
2978         stream->def_sample_flags = flags;
2979
2980       next:
2981         /* iterate all siblings */
2982         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2983             &trex_data);
2984       }
2985     }
2986   }
2987
2988   *ds_duration = stream->def_sample_duration;
2989   *ds_size = stream->def_sample_size;
2990   *ds_flags = stream->def_sample_flags;
2991
2992   /* even then, above values are better than random ... */
2993   if (G_UNLIKELY (!stream->parsed_trex)) {
2994     GST_WARNING_OBJECT (qtdemux,
2995         "failed to find fragment defaults for stream %d", stream->track_id);
2996     return FALSE;
2997   }
2998
2999   return TRUE;
3000 }
3001
3002 /* This method should be called whenever a more accurate duration might
3003  * have been found. It will update all relevant variables if/where needed
3004  */
3005 static void
3006 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3007 {
3008   guint i;
3009   guint64 movdur;
3010   GstClockTime prevdur;
3011
3012   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3013
3014   if (movdur > qtdemux->duration) {
3015     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3016     GST_DEBUG_OBJECT (qtdemux,
3017         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3018         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3019     qtdemux->duration = movdur;
3020     GST_DEBUG_OBJECT (qtdemux,
3021         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3022         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3023         GST_TIME_ARGS (qtdemux->segment.stop));
3024     if (qtdemux->segment.duration == prevdur) {
3025       /* If the current segment has duration/stop identical to previous duration
3026        * update them also (because they were set at that point in time with
3027        * the wrong duration */
3028       /* We convert the value *from* the timescale version to avoid rounding errors */
3029       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3030       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3031       qtdemux->segment.duration = fixeddur;
3032       qtdemux->segment.stop = fixeddur;
3033     }
3034   }
3035   for (i = 0; i < qtdemux->n_streams; i++) {
3036     QtDemuxStream *stream = qtdemux->streams[i];
3037     if (stream) {
3038       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3039       if (movdur > stream->duration) {
3040         GST_DEBUG_OBJECT (qtdemux,
3041             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3042             GST_TIME_ARGS (duration));
3043         stream->duration = movdur;
3044         if (stream->dummy_segment) {
3045           /* Update all dummy values to new duration */
3046           stream->segments[0].stop_time = duration;
3047           stream->segments[0].duration = duration;
3048           stream->segments[0].media_stop = duration;
3049
3050           /* let downstream know we possibly have a new stop time */
3051           if (stream->segment_index != -1) {
3052             GstClockTime pos;
3053
3054             if (qtdemux->segment.rate >= 0) {
3055               pos = stream->segment.start;
3056             } else {
3057               pos = stream->segment.stop;
3058             }
3059
3060             gst_qtdemux_stream_update_segment (qtdemux, stream,
3061                 stream->segment_index, pos, NULL, NULL);
3062           }
3063         }
3064       }
3065     }
3066   }
3067 }
3068
3069 static gboolean
3070 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3071     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3072     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3073     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3074     gboolean has_tfdt)
3075 {
3076   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3077   guint64 timestamp;
3078   gint32 data_offset = 0;
3079   guint32 flags = 0, first_flags = 0, samples_count = 0;
3080   gint i;
3081   guint8 *data;
3082   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3083   QtDemuxSample *sample;
3084   gboolean ismv = FALSE;
3085   gint64 initial_offset;
3086
3087   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3088       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3089       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3090       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3091
3092   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3093     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3094     return TRUE;
3095   }
3096
3097   /* presence of stss or not can't really tell us much,
3098    * and flags and so on tend to be marginally reliable in these files */
3099   if (stream->subtype == FOURCC_soun) {
3100     GST_DEBUG_OBJECT (qtdemux,
3101         "sound track in fragmented file; marking all keyframes");
3102     stream->all_keyframe = TRUE;
3103   }
3104
3105   if (!gst_byte_reader_skip (trun, 1) ||
3106       !gst_byte_reader_get_uint24_be (trun, &flags))
3107     goto fail;
3108
3109   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3110     goto fail;
3111
3112   if (flags & TR_DATA_OFFSET) {
3113     /* note this is really signed */
3114     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3115       goto fail;
3116     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3117     /* default base offset = first byte of moof */
3118     if (*base_offset == -1) {
3119       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3120       *base_offset = moof_offset;
3121     }
3122     *running_offset = *base_offset + data_offset;
3123   } else {
3124     /* if no offset at all, that would mean data starts at moof start,
3125      * which is a bit wrong and is ismv crappy way, so compensate
3126      * assuming data is in mdat following moof */
3127     if (*base_offset == -1) {
3128       *base_offset = moof_offset + moof_length + 8;
3129       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3130       ismv = TRUE;
3131     }
3132     if (*running_offset == -1)
3133       *running_offset = *base_offset;
3134   }
3135
3136   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3137       *running_offset);
3138   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3139       data_offset, flags, samples_count);
3140
3141   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3142     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3143       GST_DEBUG_OBJECT (qtdemux,
3144           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3145       flags ^= TR_FIRST_SAMPLE_FLAGS;
3146     } else {
3147       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3148         goto fail;
3149       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3150     }
3151   }
3152
3153   /* FIXME ? spec says other bits should also be checked to determine
3154    * entry size (and prefix size for that matter) */
3155   entry_size = 0;
3156   dur_offset = size_offset = 0;
3157   if (flags & TR_SAMPLE_DURATION) {
3158     GST_LOG_OBJECT (qtdemux, "entry duration present");
3159     dur_offset = entry_size;
3160     entry_size += 4;
3161   }
3162   if (flags & TR_SAMPLE_SIZE) {
3163     GST_LOG_OBJECT (qtdemux, "entry size present");
3164     size_offset = entry_size;
3165     entry_size += 4;
3166   }
3167   if (flags & TR_SAMPLE_FLAGS) {
3168     GST_LOG_OBJECT (qtdemux, "entry flags present");
3169     flags_offset = entry_size;
3170     entry_size += 4;
3171   }
3172   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3173     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3174     ct_offset = entry_size;
3175     entry_size += 4;
3176   }
3177
3178   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3179     goto fail;
3180   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3181
3182   if (stream->n_samples + samples_count >=
3183       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3184     goto index_too_big;
3185
3186   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3187       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3188       (stream->n_samples + samples_count) *
3189       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3190
3191   /* create a new array of samples if it's the first sample parsed */
3192   if (stream->n_samples == 0) {
3193     g_assert (stream->samples == NULL);
3194     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3195     /* or try to reallocate it with space enough to insert the new samples */
3196   } else
3197     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3198         stream->n_samples + samples_count);
3199   if (stream->samples == NULL)
3200     goto out_of_memory;
3201
3202   if (qtdemux->fragment_start != -1) {
3203     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3204     qtdemux->fragment_start = -1;
3205   } else {
3206     if (stream->n_samples == 0) {
3207       if (decode_ts > 0) {
3208         timestamp = decode_ts;
3209       } else if (stream->pending_seek != NULL) {
3210         /* if we don't have a timestamp from a tfdt box, we'll use the one
3211          * from the mfra seek table */
3212         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3213             GST_TIME_ARGS (stream->pending_seek->ts));
3214
3215         /* FIXME: this is not fully correct, the timestamp refers to the random
3216          * access sample refered to in the tfra entry, which may not necessarily
3217          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3218         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3219       } else {
3220         timestamp = 0;
3221       }
3222
3223       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3224       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3225           GST_TIME_ARGS (gst_ts));
3226     } else {
3227       /* subsequent fragments extend stream */
3228       timestamp =
3229           stream->samples[stream->n_samples - 1].timestamp +
3230           stream->samples[stream->n_samples - 1].duration;
3231
3232       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3233        * difference (1 sec.) between decode_ts and timestamp, prefer the
3234        * former */
3235       if (has_tfdt && !qtdemux->upstream_format_is_time
3236           && ABSDIFF (decode_ts, timestamp) >
3237           MAX (stream->duration_last_moof / 2,
3238               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3239         GST_INFO_OBJECT (qtdemux,
3240             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3241             ") are significantly different (more than %" GST_TIME_FORMAT
3242             "), using decode_ts",
3243             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3244             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3245             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3246                     MAX (stream->duration_last_moof / 2,
3247                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3248         timestamp = decode_ts;
3249       }
3250
3251       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3252       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3253           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3254     }
3255   }
3256
3257   initial_offset = *running_offset;
3258
3259   sample = stream->samples + stream->n_samples;
3260   for (i = 0; i < samples_count; i++) {
3261     guint32 dur, size, sflags, ct;
3262
3263     /* first read sample data */
3264     if (flags & TR_SAMPLE_DURATION) {
3265       dur = QT_UINT32 (data + dur_offset);
3266     } else {
3267       dur = d_sample_duration;
3268     }
3269     if (flags & TR_SAMPLE_SIZE) {
3270       size = QT_UINT32 (data + size_offset);
3271     } else {
3272       size = d_sample_size;
3273     }
3274     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3275       if (i == 0) {
3276         sflags = first_flags;
3277       } else {
3278         sflags = d_sample_flags;
3279       }
3280     } else if (flags & TR_SAMPLE_FLAGS) {
3281       sflags = QT_UINT32 (data + flags_offset);
3282     } else {
3283       sflags = d_sample_flags;
3284     }
3285     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3286       ct = QT_UINT32 (data + ct_offset);
3287     } else {
3288       ct = 0;
3289     }
3290     data += entry_size;
3291
3292     /* fill the sample information */
3293     sample->offset = *running_offset;
3294     sample->pts_offset = ct;
3295     sample->size = size;
3296     sample->timestamp = timestamp;
3297     sample->duration = dur;
3298     /* sample-is-difference-sample */
3299     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3300      * now idea how it relates to bitfield other than massive LE/BE confusion */
3301     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3302     *running_offset += size;
3303     timestamp += dur;
3304     stream->duration_moof += dur;
3305     sample++;
3306   }
3307
3308   /* Update total duration if needed */
3309   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3310
3311   /* Pre-emptively figure out size of mdat based on trun information.
3312    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3313    * size, else we will still be able to use this when dealing with gap'ed
3314    * input */
3315   qtdemux->mdatleft = *running_offset - initial_offset;
3316   qtdemux->mdatoffset = initial_offset;
3317   qtdemux->mdatsize = qtdemux->mdatleft;
3318
3319   stream->n_samples += samples_count;
3320   stream->n_samples_moof += samples_count;
3321
3322   if (stream->pending_seek != NULL)
3323     stream->pending_seek = NULL;
3324
3325   return TRUE;
3326
3327 fail:
3328   {
3329     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3330     return FALSE;
3331   }
3332 out_of_memory:
3333   {
3334     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3335         stream->n_samples);
3336     return FALSE;
3337   }
3338 index_too_big:
3339   {
3340     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3341         "be larger than %uMB (broken file?)", stream->n_samples,
3342         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3343     return FALSE;
3344   }
3345 }
3346
3347 /* find stream with @id */
3348 static inline QtDemuxStream *
3349 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3350 {
3351   QtDemuxStream *stream;
3352   gint i;
3353
3354   /* check */
3355   if (G_UNLIKELY (!id)) {
3356     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3357     return NULL;
3358   }
3359
3360   /* try to get it fast and simple */
3361   if (G_LIKELY (id <= qtdemux->n_streams)) {
3362     stream = qtdemux->streams[id - 1];
3363     if (G_LIKELY (stream->track_id == id))
3364       return stream;
3365   }
3366
3367   /* linear search otherwise */
3368   for (i = 0; i < qtdemux->n_streams; i++) {
3369     stream = qtdemux->streams[i];
3370     if (stream->track_id == id)
3371       return stream;
3372   }
3373   if (qtdemux->mss_mode) {
3374     /* mss should have only 1 stream anyway */
3375     return qtdemux->streams[0];
3376   }
3377
3378   return NULL;
3379 }
3380
3381 static gboolean
3382 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3383     guint32 * fragment_number)
3384 {
3385   if (!gst_byte_reader_skip (mfhd, 4))
3386     goto fail;
3387   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3388     goto fail;
3389   return TRUE;
3390 fail:
3391   {
3392     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3393     return FALSE;
3394   }
3395 }
3396
3397 static gboolean
3398 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3399     QtDemuxStream ** stream, guint32 * default_sample_duration,
3400     guint32 * default_sample_size, guint32 * default_sample_flags,
3401     gint64 * base_offset)
3402 {
3403   guint32 flags = 0;
3404   guint32 track_id = 0;
3405
3406   if (!gst_byte_reader_skip (tfhd, 1) ||
3407       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3408     goto invalid_track;
3409
3410   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3411     goto invalid_track;
3412
3413   *stream = qtdemux_find_stream (qtdemux, track_id);
3414   if (G_UNLIKELY (!*stream))
3415     goto unknown_stream;
3416
3417   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3418     *base_offset = qtdemux->moof_offset;
3419
3420   if (flags & TF_BASE_DATA_OFFSET)
3421     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3422       goto invalid_track;
3423
3424   /* obtain stream defaults */
3425   qtdemux_parse_trex (qtdemux, *stream,
3426       default_sample_duration, default_sample_size, default_sample_flags);
3427
3428   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
3429   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
3430     if (!gst_byte_reader_skip (tfhd, 4))
3431       goto invalid_track;
3432
3433   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3434     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3435       goto invalid_track;
3436
3437   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3438     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3439       goto invalid_track;
3440
3441   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3442     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3443       goto invalid_track;
3444
3445   return TRUE;
3446
3447 invalid_track:
3448   {
3449     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3450     return FALSE;
3451   }
3452 unknown_stream:
3453   {
3454     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3455     return TRUE;
3456   }
3457 }
3458
3459 static gboolean
3460 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3461     guint64 * decode_time)
3462 {
3463   guint32 version = 0;
3464
3465   if (!gst_byte_reader_get_uint32_be (br, &version))
3466     return FALSE;
3467
3468   version >>= 24;
3469   if (version == 1) {
3470     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3471       goto failed;
3472   } else {
3473     guint32 dec_time = 0;
3474     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3475       goto failed;
3476     *decode_time = dec_time;
3477   }
3478
3479   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3480       *decode_time);
3481
3482   return TRUE;
3483
3484 failed:
3485   {
3486     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3487     return FALSE;
3488   }
3489 }
3490
3491 /* Returns a pointer to a GstStructure containing the properties of
3492  * the stream sample identified by @sample_index. The caller must unref
3493  * the returned object after use. Returns NULL if unsuccessful. */
3494 static GstStructure *
3495 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3496     QtDemuxStream * stream, guint sample_index)
3497 {
3498   QtDemuxCencSampleSetInfo *info = NULL;
3499
3500   g_return_val_if_fail (stream != NULL, NULL);
3501   g_return_val_if_fail (stream->protected, NULL);
3502   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3503
3504   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3505
3506   /* Currently, cenc properties for groups of samples are not supported, so
3507    * simply return a copy of the default sample properties */
3508   return gst_structure_copy (info->default_properties);
3509 }
3510
3511 /* Parses the sizes of sample auxiliary information contained within a stream,
3512  * as given in a saiz box. Returns array of sample_count guint8 size values,
3513  * or NULL on failure */
3514 static guint8 *
3515 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3516     GstByteReader * br, guint32 * sample_count)
3517 {
3518   guint32 flags = 0;
3519   guint8 *info_sizes;
3520   guint8 default_info_size;
3521
3522   g_return_val_if_fail (qtdemux != NULL, NULL);
3523   g_return_val_if_fail (stream != NULL, NULL);
3524   g_return_val_if_fail (br != NULL, NULL);
3525   g_return_val_if_fail (sample_count != NULL, NULL);
3526
3527   if (!gst_byte_reader_get_uint32_be (br, &flags))
3528     return NULL;
3529
3530   if (flags & 0x1) {
3531     /* aux_info_type and aux_info_type_parameter are ignored */
3532     if (!gst_byte_reader_skip (br, 8))
3533       return NULL;
3534   }
3535
3536   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3537     return NULL;
3538   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3539
3540   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3541     return NULL;
3542   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3543
3544
3545   if (default_info_size == 0) {
3546     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3547       return NULL;
3548     }
3549   } else {
3550     info_sizes = g_new (guint8, *sample_count);
3551     memset (info_sizes, default_info_size, *sample_count);
3552   }
3553
3554   return info_sizes;
3555 }
3556
3557 /* Parses the offset of sample auxiliary information contained within a stream,
3558  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3559 static gboolean
3560 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3561     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3562     guint64 * offset)
3563 {
3564   guint8 version = 0;
3565   guint32 flags = 0;
3566   guint32 aux_info_type = 0;
3567   guint32 aux_info_type_parameter = 0;
3568   guint32 entry_count;
3569   guint32 off_32;
3570   guint64 off_64;
3571   const guint8 *aux_info_type_data = NULL;
3572
3573   g_return_val_if_fail (qtdemux != NULL, FALSE);
3574   g_return_val_if_fail (stream != NULL, FALSE);
3575   g_return_val_if_fail (br != NULL, FALSE);
3576   g_return_val_if_fail (offset != NULL, FALSE);
3577
3578   if (!gst_byte_reader_get_uint8 (br, &version))
3579     return FALSE;
3580
3581   if (!gst_byte_reader_get_uint24_be (br, &flags))
3582     return FALSE;
3583
3584   if (flags & 0x1) {
3585
3586     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3587       return FALSE;
3588     aux_info_type = QT_FOURCC (aux_info_type_data);
3589
3590     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3591       return FALSE;
3592   } else if (stream->protected) {
3593     aux_info_type = stream->protection_scheme_type;
3594   } else {
3595     aux_info_type = CUR_STREAM (stream)->fourcc;
3596   }
3597
3598   if (info_type)
3599     *info_type = aux_info_type;
3600   if (info_type_parameter)
3601     *info_type_parameter = aux_info_type_parameter;
3602
3603   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3604       "aux_info_type_parameter:  %#06x",
3605       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3606
3607   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3608     return FALSE;
3609
3610   if (entry_count != 1) {
3611     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3612     return FALSE;
3613   }
3614
3615   if (version == 0) {
3616     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3617       return FALSE;
3618     *offset = (guint64) off_32;
3619   } else {
3620     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3621       return FALSE;
3622     *offset = off_64;
3623   }
3624
3625   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3626   return TRUE;
3627 }
3628
3629 static void
3630 qtdemux_gst_structure_free (GstStructure * gststructure)
3631 {
3632   if (gststructure) {
3633     gst_structure_free (gststructure);
3634   }
3635 }
3636
3637 /* Parses auxiliary information relating to samples protected using Common
3638  * Encryption (cenc); the format of this information is defined in
3639  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3640 static gboolean
3641 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3642     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3643 {
3644   QtDemuxCencSampleSetInfo *ss_info = NULL;
3645   guint8 size;
3646   gint i;
3647   GPtrArray *old_crypto_info = NULL;
3648   guint old_entries = 0;
3649
3650   g_return_val_if_fail (qtdemux != NULL, FALSE);
3651   g_return_val_if_fail (stream != NULL, FALSE);
3652   g_return_val_if_fail (br != NULL, FALSE);
3653   g_return_val_if_fail (stream->protected, FALSE);
3654   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3655
3656   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3657
3658   if (ss_info->crypto_info) {
3659     old_crypto_info = ss_info->crypto_info;
3660     /* Count number of non-null entries remaining at the tail end */
3661     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3662       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3663         break;
3664       old_entries++;
3665     }
3666   }
3667
3668   ss_info->crypto_info =
3669       g_ptr_array_new_full (sample_count + old_entries,
3670       (GDestroyNotify) qtdemux_gst_structure_free);
3671
3672   /* We preserve old entries because we parse the next moof in advance
3673    * of consuming all samples from the previous moof, and otherwise
3674    * we'd discard the corresponding crypto info for the samples
3675    * from the previous fragment. */
3676   if (old_entries) {
3677     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3678         old_entries);
3679     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3680       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3681               i));
3682       g_ptr_array_index (old_crypto_info, i) = NULL;
3683     }
3684   }
3685
3686   if (old_crypto_info) {
3687     /* Everything now belongs to the new array */
3688     g_ptr_array_free (old_crypto_info, TRUE);
3689   }
3690
3691   for (i = 0; i < sample_count; ++i) {
3692     GstStructure *properties;
3693     guint16 n_subsamples = 0;
3694     guint8 *data;
3695     guint iv_size;
3696     GstBuffer *buf;
3697
3698     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3699     if (properties == NULL) {
3700       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3701       return FALSE;
3702     }
3703     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3704       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3705       gst_structure_free (properties);
3706       return FALSE;
3707     }
3708     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3709       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3710       gst_structure_free (properties);
3711       return FALSE;
3712     }
3713     buf = gst_buffer_new_wrapped (data, iv_size);
3714     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3715     gst_buffer_unref (buf);
3716     size = info_sizes[i];
3717     if (size > iv_size) {
3718       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3719           || !(n_subsamples > 0)) {
3720         gst_structure_free (properties);
3721         GST_ERROR_OBJECT (qtdemux,
3722             "failed to get subsample count for sample %u", i);
3723         return FALSE;
3724       }
3725       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3726       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3727         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3728             i);
3729         gst_structure_free (properties);
3730         return FALSE;
3731       }
3732       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3733       if (!buf) {
3734         gst_structure_free (properties);
3735         return FALSE;
3736       }
3737       gst_structure_set (properties,
3738           "subsample_count", G_TYPE_UINT, n_subsamples,
3739           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3740       gst_buffer_unref (buf);
3741     } else {
3742       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3743     }
3744     g_ptr_array_add (ss_info->crypto_info, properties);
3745   }
3746   return TRUE;
3747 }
3748
3749 /* Converts a UUID in raw byte form to a string representation, as defined in
3750  * RFC 4122. The caller takes ownership of the returned string and is
3751  * responsible for freeing it after use. */
3752 static gchar *
3753 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3754 {
3755   const guint8 *uuid = (const guint8 *) uuid_bytes;
3756
3757   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3758       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3759       uuid[0], uuid[1], uuid[2], uuid[3],
3760       uuid[4], uuid[5], uuid[6], uuid[7],
3761       uuid[8], uuid[9], uuid[10], uuid[11],
3762       uuid[12], uuid[13], uuid[14], uuid[15]);
3763 }
3764
3765 /* Parses a Protection System Specific Header box (pssh), as defined in the
3766  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3767  * information needed by a specific content protection system in order to
3768  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3769  * otherwise. */
3770 static gboolean
3771 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3772 {
3773   gchar *sysid_string;
3774   guint32 pssh_size = QT_UINT32 (node->data);
3775   GstBuffer *pssh = NULL;
3776   GstEvent *event = NULL;
3777   guint32 parent_box_type;
3778   gint i;
3779
3780   if (G_UNLIKELY (pssh_size < 32U)) {
3781     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3782     return FALSE;
3783   }
3784
3785   sysid_string =
3786       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3787
3788   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3789
3790   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3791   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3792       gst_buffer_get_size (pssh));
3793
3794   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3795
3796   /* Push an event containing the pssh box onto the queues of all streams. */
3797   event = gst_event_new_protection (sysid_string, pssh,
3798       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3799   for (i = 0; i < qtdemux->n_streams; ++i) {
3800     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3801         gst_event_ref (event));
3802   }
3803   g_free (sysid_string);
3804   gst_event_unref (event);
3805   gst_buffer_unref (pssh);
3806   return TRUE;
3807 }
3808
3809 static gboolean
3810 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3811     guint64 moof_offset, QtDemuxStream * stream)
3812 {
3813   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3814   GNode *uuid_node;
3815   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3816   GNode *saiz_node, *saio_node, *pssh_node;
3817   GstByteReader saiz_data, saio_data;
3818   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3819   gint64 base_offset, running_offset;
3820   guint32 frag_num;
3821
3822   /* NOTE @stream ignored */
3823
3824   moof_node = g_node_new ((guint8 *) buffer);
3825   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3826   qtdemux_node_dump (qtdemux, moof_node);
3827
3828   /* Get fragment number from mfhd and check it's valid */
3829   mfhd_node =
3830       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3831   if (mfhd_node == NULL)
3832     goto missing_mfhd;
3833   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3834     goto fail;
3835   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3836
3837   /* unknown base_offset to start with */
3838   base_offset = running_offset = -1;
3839   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3840   while (traf_node) {
3841     guint64 decode_time = 0;
3842
3843     /* Fragment Header node */
3844     tfhd_node =
3845         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3846         &tfhd_data);
3847     if (!tfhd_node)
3848       goto missing_tfhd;
3849     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3850             &ds_size, &ds_flags, &base_offset))
3851       goto missing_tfhd;
3852
3853     /* The following code assumes at most a single set of sample auxiliary
3854      * data in the fragment (consisting of a saiz box and a corresponding saio
3855      * box); in theory, however, there could be multiple sets of sample
3856      * auxiliary data in a fragment. */
3857     saiz_node =
3858         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3859         &saiz_data);
3860     if (saiz_node) {
3861       guint32 info_type = 0;
3862       guint64 offset = 0;
3863       guint32 info_type_parameter = 0;
3864
3865       g_free (qtdemux->cenc_aux_info_sizes);
3866
3867       qtdemux->cenc_aux_info_sizes =
3868           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3869           &qtdemux->cenc_aux_sample_count);
3870       if (qtdemux->cenc_aux_info_sizes == NULL) {
3871         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3872         goto fail;
3873       }
3874       saio_node =
3875           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3876           &saio_data);
3877       if (!saio_node) {
3878         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3879         g_free (qtdemux->cenc_aux_info_sizes);
3880         qtdemux->cenc_aux_info_sizes = NULL;
3881         goto fail;
3882       }
3883
3884       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3885                   &info_type, &info_type_parameter, &offset))) {
3886         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3887         g_free (qtdemux->cenc_aux_info_sizes);
3888         qtdemux->cenc_aux_info_sizes = NULL;
3889         goto fail;
3890       }
3891       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3892         offset += (guint64) (base_offset - qtdemux->moof_offset);
3893       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3894         GstByteReader br;
3895         if (offset > length) {
3896           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3897           qtdemux->cenc_aux_info_offset = offset;
3898         } else {
3899           gst_byte_reader_init (&br, buffer + offset, length - offset);
3900           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3901                   qtdemux->cenc_aux_info_sizes,
3902                   qtdemux->cenc_aux_sample_count)) {
3903             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3904             g_free (qtdemux->cenc_aux_info_sizes);
3905             qtdemux->cenc_aux_info_sizes = NULL;
3906             goto fail;
3907           }
3908         }
3909       }
3910     }
3911
3912     tfdt_node =
3913         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3914         &tfdt_data);
3915     if (tfdt_node) {
3916       /* We'll use decode_time to interpolate timestamps
3917        * in case the input timestamps are missing */
3918       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3919
3920       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3921           " (%" GST_TIME_FORMAT ")", decode_time,
3922           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_time)));
3923
3924       /* Discard the fragment buffer timestamp info to avoid using it.
3925        * Rely on tfdt instead as it is more accurate than the timestamp
3926        * that is fetched from a manifest/playlist and is usually
3927        * less accurate. */
3928       qtdemux->fragment_start = -1;
3929     }
3930
3931     if (G_UNLIKELY (!stream)) {
3932       /* we lost track of offset, we'll need to regain it,
3933        * but can delay complaining until later or avoid doing so altogether */
3934       base_offset = -2;
3935       goto next;
3936     }
3937     if (G_UNLIKELY (base_offset < -1))
3938       goto lost_offset;
3939
3940     if (qtdemux->upstream_format_is_time)
3941       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3942
3943     /* initialise moof sample data */
3944     stream->n_samples_moof = 0;
3945     stream->duration_last_moof = stream->duration_moof;
3946     stream->duration_moof = 0;
3947
3948     /* Track Run node */
3949     trun_node =
3950         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3951         &trun_data);
3952     while (trun_node) {
3953       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3954           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3955           &running_offset, decode_time, (tfdt_node != NULL));
3956       /* iterate all siblings */
3957       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3958           &trun_data);
3959     }
3960
3961     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3962     if (uuid_node) {
3963       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3964       guint32 box_length = QT_UINT32 (uuid_buffer);
3965
3966       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3967     }
3968
3969     /* if no new base_offset provided for next traf,
3970      * base is end of current traf */
3971     base_offset = running_offset;
3972     running_offset = -1;
3973
3974     if (stream->n_samples_moof && stream->duration_moof)
3975       stream->new_caps = TRUE;
3976
3977   next:
3978     /* iterate all siblings */
3979     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3980   }
3981
3982   /* parse any protection system info */
3983   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3984   while (pssh_node) {
3985     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3986     qtdemux_parse_pssh (qtdemux, pssh_node);
3987     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3988   }
3989
3990   g_node_destroy (moof_node);
3991   return TRUE;
3992
3993 missing_tfhd:
3994   {
3995     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3996     goto fail;
3997   }
3998 missing_mfhd:
3999   {
4000     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4001     goto fail;
4002   }
4003 lost_offset:
4004   {
4005     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4006     goto fail;
4007   }
4008 fail:
4009   {
4010     g_node_destroy (moof_node);
4011     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4012         (_("This file is corrupt and cannot be played.")), (NULL));
4013     return FALSE;
4014   }
4015 }
4016
4017 #if 0
4018 /* might be used if some day we actually use mfra & co
4019  * for random access to fragments,
4020  * but that will require quite some modifications and much less relying
4021  * on a sample array */
4022 #endif
4023
4024 static gboolean
4025 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4026 {
4027   QtDemuxStream *stream;
4028   guint32 ver_flags, track_id, len, num_entries, i;
4029   guint value_size, traf_size, trun_size, sample_size;
4030   guint64 time = 0, moof_offset = 0;
4031 #if 0
4032   GstBuffer *buf = NULL;
4033   GstFlowReturn ret;
4034 #endif
4035   GstByteReader tfra;
4036
4037   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4038
4039   if (!gst_byte_reader_skip (&tfra, 8))
4040     return FALSE;
4041
4042   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4043     return FALSE;
4044
4045   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4046       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4047       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4048     return FALSE;
4049
4050   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4051
4052   stream = qtdemux_find_stream (qtdemux, track_id);
4053   if (stream == NULL)
4054     goto unknown_trackid;
4055
4056   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4057   sample_size = (len & 3) + 1;
4058   trun_size = ((len & 12) >> 2) + 1;
4059   traf_size = ((len & 48) >> 4) + 1;
4060
4061   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4062       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4063
4064   if (num_entries == 0)
4065     goto no_samples;
4066
4067   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4068           value_size + value_size + traf_size + trun_size + sample_size))
4069     goto corrupt_file;
4070
4071   g_free (stream->ra_entries);
4072   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4073   stream->n_ra_entries = num_entries;
4074
4075   for (i = 0; i < num_entries; i++) {
4076     qt_atom_parser_get_offset (&tfra, value_size, &time);
4077     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4078     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4079     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4080     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4081
4082     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4083
4084     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4085         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4086
4087     stream->ra_entries[i].ts = time;
4088     stream->ra_entries[i].moof_offset = moof_offset;
4089
4090     /* don't want to go through the entire file and read all moofs at startup */
4091 #if 0
4092     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4093     if (ret != GST_FLOW_OK)
4094       goto corrupt_file;
4095     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4096         moof_offset, stream);
4097     gst_buffer_unref (buf);
4098 #endif
4099   }
4100
4101   check_update_duration (qtdemux, time);
4102
4103   return TRUE;
4104
4105 /* ERRORS */
4106 unknown_trackid:
4107   {
4108     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4109     return FALSE;
4110   }
4111 corrupt_file:
4112   {
4113     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4114     return FALSE;
4115   }
4116 no_samples:
4117   {
4118     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4119     return FALSE;
4120   }
4121 }
4122
4123 static gboolean
4124 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4125 {
4126   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4127   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4128   GstBuffer *mfro = NULL, *mfra = NULL;
4129   GstFlowReturn flow;
4130   gboolean ret = FALSE;
4131   GNode *mfra_node, *tfra_node;
4132   guint64 mfra_offset = 0;
4133   guint32 fourcc, mfra_size;
4134   gint64 len;
4135
4136   /* query upstream size in bytes */
4137   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4138     goto size_query_failed;
4139
4140   /* mfro box should be at the very end of the file */
4141   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4142   if (flow != GST_FLOW_OK)
4143     goto exit;
4144
4145   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4146
4147   fourcc = QT_FOURCC (mfro_map.data + 4);
4148   if (fourcc != FOURCC_mfro)
4149     goto exit;
4150
4151   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4152   if (mfro_map.size < 16)
4153     goto invalid_mfro_size;
4154
4155   mfra_size = QT_UINT32 (mfro_map.data + 12);
4156   if (mfra_size >= len)
4157     goto invalid_mfra_size;
4158
4159   mfra_offset = len - mfra_size;
4160
4161   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4162       mfra_offset, mfra_size);
4163
4164   /* now get and parse mfra box */
4165   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4166   if (flow != GST_FLOW_OK)
4167     goto broken_file;
4168
4169   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4170
4171   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4172   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4173
4174   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4175
4176   while (tfra_node) {
4177     qtdemux_parse_tfra (qtdemux, tfra_node);
4178     /* iterate all siblings */
4179     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4180   }
4181   g_node_destroy (mfra_node);
4182
4183   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4184   ret = TRUE;
4185
4186 exit:
4187
4188   if (mfro) {
4189     if (mfro_map.memory != NULL)
4190       gst_buffer_unmap (mfro, &mfro_map);
4191     gst_buffer_unref (mfro);
4192   }
4193   if (mfra) {
4194     if (mfra_map.memory != NULL)
4195       gst_buffer_unmap (mfra, &mfra_map);
4196     gst_buffer_unref (mfra);
4197   }
4198   return ret;
4199
4200 /* ERRORS */
4201 size_query_failed:
4202   {
4203     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4204     goto exit;
4205   }
4206 invalid_mfro_size:
4207   {
4208     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4209     goto exit;
4210   }
4211 invalid_mfra_size:
4212   {
4213     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4214     goto exit;
4215   }
4216 broken_file:
4217   {
4218     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4219     goto exit;
4220   }
4221 }
4222
4223 static guint64
4224 add_offset (guint64 offset, guint64 advance)
4225 {
4226   /* Avoid 64-bit overflow by clamping */
4227   if (offset > G_MAXUINT64 - advance)
4228     return G_MAXUINT64;
4229   return offset + advance;
4230 }
4231
4232 static GstFlowReturn
4233 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4234 {
4235   guint64 length = 0;
4236   guint32 fourcc = 0;
4237   GstBuffer *buf = NULL;
4238   GstFlowReturn ret = GST_FLOW_OK;
4239   guint64 cur_offset = qtdemux->offset;
4240   GstMapInfo map;
4241
4242   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4243   if (G_UNLIKELY (ret != GST_FLOW_OK))
4244     goto beach;
4245   gst_buffer_map (buf, &map, GST_MAP_READ);
4246   if (G_LIKELY (map.size >= 8))
4247     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4248   gst_buffer_unmap (buf, &map);
4249   gst_buffer_unref (buf);
4250
4251   /* maybe we already got most we needed, so only consider this eof */
4252   if (G_UNLIKELY (length == 0)) {
4253     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4254         (_("Invalid atom size.")),
4255         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4256             GST_FOURCC_ARGS (fourcc)));
4257     ret = GST_FLOW_EOS;
4258     goto beach;
4259   }
4260
4261   switch (fourcc) {
4262     case FOURCC_moof:
4263       /* record for later parsing when needed */
4264       if (!qtdemux->moof_offset) {
4265         qtdemux->moof_offset = qtdemux->offset;
4266       }
4267       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4268         /* FIXME */
4269       } else {
4270         qtdemux->offset += length;      /* skip moof and keep going */
4271       }
4272       if (qtdemux->got_moov) {
4273         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4274         ret = GST_FLOW_EOS;
4275         goto beach;
4276       }
4277       break;
4278     case FOURCC_mdat:
4279     case FOURCC_free:
4280     case FOURCC_wide:
4281     case FOURCC_PICT:
4282     case FOURCC_pnot:
4283     {
4284       GST_LOG_OBJECT (qtdemux,
4285           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4286           GST_FOURCC_ARGS (fourcc), cur_offset);
4287       qtdemux->offset = add_offset (qtdemux->offset, length);
4288       break;
4289     }
4290     case FOURCC_moov:
4291     {
4292       GstBuffer *moov = NULL;
4293
4294       if (qtdemux->got_moov) {
4295         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4296         qtdemux->offset = add_offset (qtdemux->offset, length);
4297         goto beach;
4298       }
4299
4300       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4301       if (ret != GST_FLOW_OK)
4302         goto beach;
4303       gst_buffer_map (moov, &map, GST_MAP_READ);
4304
4305       if (length != map.size) {
4306         /* Some files have a 'moov' atom at the end of the file which contains
4307          * a terminal 'free' atom where the body of the atom is missing.
4308          * Check for, and permit, this special case.
4309          */
4310         if (map.size >= 8) {
4311           guint8 *final_data = map.data + (map.size - 8);
4312           guint32 final_length = QT_UINT32 (final_data);
4313           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4314
4315           if (final_fourcc == FOURCC_free
4316               && map.size + final_length - 8 == length) {
4317             /* Ok, we've found that special case. Allocate a new buffer with
4318              * that free atom actually present. */
4319             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4320             gst_buffer_fill (newmoov, 0, map.data, map.size);
4321             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4322             gst_buffer_unmap (moov, &map);
4323             gst_buffer_unref (moov);
4324             moov = newmoov;
4325             gst_buffer_map (moov, &map, GST_MAP_READ);
4326           }
4327         }
4328       }
4329
4330       if (length != map.size) {
4331         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4332             (_("This file is incomplete and cannot be played.")),
4333             ("We got less than expected (received %" G_GSIZE_FORMAT
4334                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4335                 (guint) length, cur_offset));
4336         gst_buffer_unmap (moov, &map);
4337         gst_buffer_unref (moov);
4338         ret = GST_FLOW_ERROR;
4339         goto beach;
4340       }
4341       qtdemux->offset += length;
4342
4343       qtdemux_parse_moov (qtdemux, map.data, length);
4344       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4345
4346       qtdemux_parse_tree (qtdemux);
4347       if (qtdemux->moov_node_compressed) {
4348         g_node_destroy (qtdemux->moov_node_compressed);
4349         g_free (qtdemux->moov_node->data);
4350       }
4351       qtdemux->moov_node_compressed = NULL;
4352       g_node_destroy (qtdemux->moov_node);
4353       qtdemux->moov_node = NULL;
4354       gst_buffer_unmap (moov, &map);
4355       gst_buffer_unref (moov);
4356       qtdemux->got_moov = TRUE;
4357
4358       break;
4359     }
4360     case FOURCC_ftyp:
4361     {
4362       GstBuffer *ftyp = NULL;
4363
4364       /* extract major brand; might come in handy for ISO vs QT issues */
4365       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4366       if (ret != GST_FLOW_OK)
4367         goto beach;
4368       qtdemux->offset += length;
4369       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4370       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4371       gst_buffer_unmap (ftyp, &map);
4372       gst_buffer_unref (ftyp);
4373       break;
4374     }
4375     case FOURCC_uuid:
4376     {
4377       GstBuffer *uuid = NULL;
4378
4379       /* uuid are extension atoms */
4380       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4381       if (ret != GST_FLOW_OK)
4382         goto beach;
4383       qtdemux->offset += length;
4384       gst_buffer_map (uuid, &map, GST_MAP_READ);
4385       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4386       gst_buffer_unmap (uuid, &map);
4387       gst_buffer_unref (uuid);
4388       break;
4389     }
4390     case FOURCC_sidx:
4391     {
4392       GstBuffer *sidx = NULL;
4393       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4394       if (ret != GST_FLOW_OK)
4395         goto beach;
4396       qtdemux->offset += length;
4397       gst_buffer_map (sidx, &map, GST_MAP_READ);
4398       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4399       gst_buffer_unmap (sidx, &map);
4400       gst_buffer_unref (sidx);
4401       break;
4402     }
4403     default:
4404     {
4405       GstBuffer *unknown = NULL;
4406
4407       GST_LOG_OBJECT (qtdemux,
4408           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4409           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4410           cur_offset);
4411       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4412       if (ret != GST_FLOW_OK)
4413         goto beach;
4414       gst_buffer_map (unknown, &map, GST_MAP_READ);
4415       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4416       gst_buffer_unmap (unknown, &map);
4417       gst_buffer_unref (unknown);
4418       qtdemux->offset += length;
4419       break;
4420     }
4421   }
4422
4423 beach:
4424   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4425     /* digested all data, show what we have */
4426     qtdemux_prepare_streams (qtdemux);
4427     ret = qtdemux_expose_streams (qtdemux);
4428
4429     qtdemux->state = QTDEMUX_STATE_MOVIE;
4430     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4431         qtdemux->state);
4432     return ret;
4433   }
4434   return ret;
4435 }
4436
4437 /* Seeks to the previous keyframe of the indexed stream and
4438  * aligns other streams with respect to the keyframe timestamp
4439  * of indexed stream. Only called in case of Reverse Playback
4440  */
4441 static GstFlowReturn
4442 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4443 {
4444   guint8 n = 0;
4445   guint32 seg_idx = 0, k_index = 0;
4446   guint32 ref_seg_idx, ref_k_index;
4447   GstClockTime k_pos = 0, last_stop = 0;
4448   QtDemuxSegment *seg = NULL;
4449   QtDemuxStream *ref_str = NULL;
4450   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4451   guint64 target_ts;
4452
4453   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4454    * and finally align all the other streams on that timestamp with their
4455    * respective keyframes */
4456   for (n = 0; n < qtdemux->n_streams; n++) {
4457     QtDemuxStream *str = qtdemux->streams[n];
4458
4459     /* No candidate yet, take the first stream */
4460     if (!ref_str) {
4461       ref_str = str;
4462       continue;
4463     }
4464
4465     /* So that stream has a segment, we prefer video streams */
4466     if (str->subtype == FOURCC_vide) {
4467       ref_str = str;
4468       break;
4469     }
4470   }
4471
4472   if (G_UNLIKELY (!ref_str)) {
4473     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4474     goto eos;
4475   }
4476
4477   if (G_UNLIKELY (!ref_str->from_sample)) {
4478     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4479     goto eos;
4480   }
4481
4482   /* So that stream has been playing from from_sample to to_sample. We will
4483    * get the timestamp of the previous sample and search for a keyframe before
4484    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4485   if (ref_str->subtype == FOURCC_vide) {
4486     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4487         ref_str->from_sample - 1, FALSE);
4488   } else {
4489     if (ref_str->from_sample >= 10)
4490       k_index = ref_str->from_sample - 10;
4491     else
4492       k_index = 0;
4493   }
4494
4495   target_ts =
4496       ref_str->samples[k_index].timestamp +
4497       ref_str->samples[k_index].pts_offset;
4498
4499   /* get current segment for that stream */
4500   seg = &ref_str->segments[ref_str->segment_index];
4501   /* Use segment start in original timescale for comparisons */
4502   seg_media_start_mov = seg->trak_media_start;
4503
4504   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4505       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4506       k_index, target_ts, seg_media_start_mov,
4507       GST_TIME_ARGS (seg->media_start));
4508
4509   /* Crawl back through segments to find the one containing this I frame */
4510   while (target_ts < seg_media_start_mov) {
4511     GST_DEBUG_OBJECT (qtdemux,
4512         "keyframe position (sample %u) is out of segment %u " " target %"
4513         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4514         ref_str->segment_index, target_ts, seg_media_start_mov);
4515
4516     if (G_UNLIKELY (!ref_str->segment_index)) {
4517       /* Reached first segment, let's consider it's EOS */
4518       goto eos;
4519     }
4520     ref_str->segment_index--;
4521     seg = &ref_str->segments[ref_str->segment_index];
4522     /* Use segment start in original timescale for comparisons */
4523     seg_media_start_mov = seg->trak_media_start;
4524   }
4525   /* Calculate time position of the keyframe and where we should stop */
4526   k_pos =
4527       QTSTREAMTIME_TO_GSTTIME (ref_str,
4528       target_ts - seg->trak_media_start) + seg->time;
4529   last_stop =
4530       QTSTREAMTIME_TO_GSTTIME (ref_str,
4531       ref_str->samples[ref_str->from_sample].timestamp -
4532       seg->trak_media_start) + seg->time;
4533
4534   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4535       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4536       k_index, GST_TIME_ARGS (k_pos));
4537
4538   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4539   qtdemux->segment.position = last_stop;
4540   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4541       GST_TIME_ARGS (last_stop));
4542
4543   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4544     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4545     goto eos;
4546   }
4547
4548   ref_seg_idx = ref_str->segment_index;
4549   ref_k_index = k_index;
4550
4551   /* Align them all on this */
4552   for (n = 0; n < qtdemux->n_streams; n++) {
4553     guint32 index = 0;
4554     GstClockTime seg_time = 0;
4555     QtDemuxStream *str = qtdemux->streams[n];
4556
4557     /* aligning reference stream again might lead to backing up to yet another
4558      * keyframe (due to timestamp rounding issues),
4559      * potentially putting more load on downstream; so let's try to avoid */
4560     if (str == ref_str) {
4561       seg_idx = ref_seg_idx;
4562       seg = &str->segments[seg_idx];
4563       k_index = ref_k_index;
4564       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4565           "sample at index %d", n, ref_str->segment_index, k_index);
4566     } else {
4567       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4568       GST_DEBUG_OBJECT (qtdemux,
4569           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4570           seg_idx, GST_TIME_ARGS (k_pos));
4571
4572       /* get segment and time in the segment */
4573       seg = &str->segments[seg_idx];
4574       seg_time = k_pos - seg->time;
4575
4576       /* get the media time in the segment.
4577        * No adjustment for empty "filler" segments */
4578       if (seg->media_start != GST_CLOCK_TIME_NONE)
4579         seg_time += seg->media_start;
4580
4581       /* get the index of the sample with media time */
4582       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4583       GST_DEBUG_OBJECT (qtdemux,
4584           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4585           GST_TIME_ARGS (seg_time), index);
4586
4587       /* find previous keyframe */
4588       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4589     }
4590
4591     /* Remember until where we want to go */
4592     str->to_sample = str->from_sample - 1;
4593     /* Define our time position */
4594     target_ts =
4595         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4596     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4597     if (seg->media_start != GST_CLOCK_TIME_NONE)
4598       str->time_position -= seg->media_start;
4599
4600     /* Now seek back in time */
4601     gst_qtdemux_move_stream (qtdemux, str, k_index);
4602     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4603         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4604         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4605   }
4606
4607   return GST_FLOW_OK;
4608
4609 eos:
4610   return GST_FLOW_EOS;
4611 }
4612
4613 /*
4614  * Gets the current qt segment start, stop and position for the
4615  * given time offset. This is used in update_segment()
4616  */
4617 static void
4618 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4619     QtDemuxStream * stream, GstClockTime offset,
4620     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4621 {
4622   GstClockTime seg_time;
4623   GstClockTime start, stop, time;
4624   QtDemuxSegment *segment;
4625
4626   segment = &stream->segments[stream->segment_index];
4627
4628   /* get time in this segment */
4629   seg_time = (offset - segment->time) * segment->rate;
4630
4631   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4632       GST_TIME_ARGS (seg_time));
4633
4634   if (G_UNLIKELY (seg_time > segment->duration)) {
4635     GST_LOG_OBJECT (stream->pad,
4636         "seg_time > segment->duration %" GST_TIME_FORMAT,
4637         GST_TIME_ARGS (segment->duration));
4638     seg_time = segment->duration;
4639   }
4640
4641   /* qtdemux->segment.stop is in outside-time-realm, whereas
4642    * segment->media_stop is in track-time-realm.
4643    *
4644    * In order to compare the two, we need to bring segment.stop
4645    * into the track-time-realm
4646    *
4647    * FIXME - does this comment still hold? Don't see any conversion here */
4648
4649   stop = qtdemux->segment.stop;
4650   if (stop == GST_CLOCK_TIME_NONE)
4651     stop = qtdemux->segment.duration;
4652   if (stop == GST_CLOCK_TIME_NONE)
4653     stop = segment->media_stop;
4654   else
4655     stop =
4656         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4657
4658   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4659     start = segment->time + seg_time;
4660     time = offset;
4661     stop = start - seg_time + segment->duration;
4662   } else if (qtdemux->segment.rate >= 0) {
4663     start = MIN (segment->media_start + seg_time, stop);
4664     time = offset;
4665   } else {
4666     if (segment->media_start >= qtdemux->segment.start) {
4667       time = segment->time;
4668     } else {
4669       time = segment->time + (qtdemux->segment.start - segment->media_start);
4670     }
4671
4672     start = MAX (segment->media_start, qtdemux->segment.start);
4673     stop = MIN (segment->media_start + seg_time, stop);
4674   }
4675
4676   *_start = start;
4677   *_stop = stop;
4678   *_time = time;
4679 }
4680
4681 /*
4682  * Updates the qt segment used for the stream and pushes a new segment event
4683  * downstream on this stream's pad.
4684  */
4685 static gboolean
4686 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4687     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4688     GstClockTime * _stop)
4689 {
4690   QtDemuxSegment *segment;
4691   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4692   gdouble rate;
4693   GstEvent *event;
4694
4695   /* update the current segment */
4696   stream->segment_index = seg_idx;
4697
4698   /* get the segment */
4699   segment = &stream->segments[seg_idx];
4700
4701   if (G_UNLIKELY (offset < segment->time)) {
4702     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4703         GST_TIME_ARGS (segment->time));
4704     return FALSE;
4705   }
4706
4707   /* segment lies beyond total indicated duration */
4708   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4709           segment->time > qtdemux->segment.duration)) {
4710     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4711         " < segment->time %" GST_TIME_FORMAT,
4712         GST_TIME_ARGS (qtdemux->segment.duration),
4713         GST_TIME_ARGS (segment->time));
4714     return FALSE;
4715   }
4716
4717   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4718       &start, &stop, &time);
4719
4720   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4721       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4722       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4723
4724   /* combine global rate with that of the segment */
4725   rate = segment->rate * qtdemux->segment.rate;
4726
4727   /* Copy flags from main segment */
4728   stream->segment.flags = qtdemux->segment.flags;
4729
4730   /* update the segment values used for clipping */
4731   stream->segment.offset = qtdemux->segment.offset;
4732   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4733   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4734   stream->segment.rate = rate;
4735   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4736       stream->cslg_shift);
4737   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4738       stream->cslg_shift);
4739   stream->segment.time = time;
4740   stream->segment.position = stream->segment.start;
4741
4742   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4743       &stream->segment);
4744
4745   /* now prepare and send the segment */
4746   if (stream->pad) {
4747     event = gst_event_new_segment (&stream->segment);
4748     if (qtdemux->segment_seqnum) {
4749       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4750     }
4751     gst_pad_push_event (stream->pad, event);
4752     /* assume we can send more data now */
4753     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4754     /* clear to send tags on this pad now */
4755     gst_qtdemux_push_tags (qtdemux, stream);
4756   }
4757
4758   if (_start)
4759     *_start = start;
4760   if (_stop)
4761     *_stop = stop;
4762
4763   return TRUE;
4764 }
4765
4766 /* activate the given segment number @seg_idx of @stream at time @offset.
4767  * @offset is an absolute global position over all the segments.
4768  *
4769  * This will push out a NEWSEGMENT event with the right values and
4770  * position the stream index to the first decodable sample before
4771  * @offset.
4772  */
4773 static gboolean
4774 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4775     guint32 seg_idx, GstClockTime offset)
4776 {
4777   QtDemuxSegment *segment;
4778   guint32 index, kf_index;
4779   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4780
4781   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4782       seg_idx, GST_TIME_ARGS (offset));
4783
4784   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4785           &start, &stop))
4786     return FALSE;
4787
4788   segment = &stream->segments[stream->segment_index];
4789
4790   /* in the fragmented case, we pick a fragment that starts before our
4791    * desired position and rely on downstream to wait for a keyframe
4792    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4793    * tfra entries tells us which trun/sample the key unit is in, but we don't
4794    * make use of this additional information at the moment) */
4795   if (qtdemux->fragmented) {
4796     stream->to_sample = G_MAXUINT32;
4797     return TRUE;
4798   }
4799
4800   /* We don't need to look for a sample in push-based */
4801   if (!qtdemux->pullbased)
4802     return TRUE;
4803
4804   /* and move to the keyframe before the indicated media time of the
4805    * segment */
4806   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4807     if (qtdemux->segment.rate >= 0) {
4808       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4809       stream->to_sample = G_MAXUINT32;
4810       GST_DEBUG_OBJECT (stream->pad,
4811           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4812           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4813           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4814     } else {
4815       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4816       stream->to_sample = index;
4817       GST_DEBUG_OBJECT (stream->pad,
4818           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4819           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4820           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4821     }
4822   } else {
4823     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4824         "this is an empty segment");
4825     return TRUE;
4826   }
4827
4828   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4829    * encountered an error and printed a message so we return appropriately */
4830   if (index == -1)
4831     return FALSE;
4832
4833   /* we're at the right spot */
4834   if (index == stream->sample_index) {
4835     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4836     return TRUE;
4837   }
4838
4839   /* find keyframe of the target index */
4840   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4841
4842 /* *INDENT-OFF* */
4843 /* indent does stupid stuff with stream->samples[].timestamp */
4844
4845   /* if we move forwards, we don't have to go back to the previous
4846    * keyframe since we already sent that. We can also just jump to
4847    * the keyframe right before the target index if there is one. */
4848   if (index > stream->sample_index) {
4849     /* moving forwards check if we move past a keyframe */
4850     if (kf_index > stream->sample_index) {
4851       GST_DEBUG_OBJECT (stream->pad,
4852            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4853            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4854            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4855       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4856     } else {
4857       GST_DEBUG_OBJECT (stream->pad,
4858           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4859           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4860           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4861     }
4862   } else {
4863     GST_DEBUG_OBJECT (stream->pad,
4864         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4865         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4866         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4867     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4868   }
4869
4870 /* *INDENT-ON* */
4871
4872   return TRUE;
4873 }
4874
4875 /* prepare to get the current sample of @stream, getting essential values.
4876  *
4877  * This function will also prepare and send the segment when needed.
4878  *
4879  * Return FALSE if the stream is EOS.
4880  *
4881  * PULL-BASED
4882  */
4883 static gboolean
4884 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4885     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4886     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4887     gboolean * keyframe)
4888 {
4889   QtDemuxSample *sample;
4890   GstClockTime time_position;
4891   guint32 seg_idx;
4892
4893   g_return_val_if_fail (stream != NULL, FALSE);
4894
4895   time_position = stream->time_position;
4896   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4897     goto eos;
4898
4899   seg_idx = stream->segment_index;
4900   if (G_UNLIKELY (seg_idx == -1)) {
4901     /* find segment corresponding to time_position if we are looking
4902      * for a segment. */
4903     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4904   }
4905
4906   /* different segment, activate it, sample_index will be set. */
4907   if (G_UNLIKELY (stream->segment_index != seg_idx))
4908     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4909
4910   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4911                   segment_index]))) {
4912     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4913
4914     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4915         " prepare empty sample");
4916
4917     *empty = TRUE;
4918     *pts = *dts = time_position;
4919     *duration = seg->duration - (time_position - seg->time);
4920
4921     return TRUE;
4922   }
4923
4924   *empty = FALSE;
4925
4926   if (stream->sample_index == -1)
4927     stream->sample_index = 0;
4928
4929   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4930       stream->sample_index, stream->n_samples);
4931
4932   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4933     if (!qtdemux->fragmented)
4934       goto eos;
4935
4936     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4937     do {
4938       GstFlowReturn flow;
4939
4940       GST_OBJECT_LOCK (qtdemux);
4941       flow = qtdemux_add_fragmented_samples (qtdemux);
4942       GST_OBJECT_UNLOCK (qtdemux);
4943
4944       if (flow != GST_FLOW_OK)
4945         goto eos;
4946     }
4947     while (stream->sample_index >= stream->n_samples);
4948   }
4949
4950   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4951     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4952         stream->sample_index);
4953     return FALSE;
4954   }
4955
4956   /* now get the info for the sample we're at */
4957   sample = &stream->samples[stream->sample_index];
4958
4959   *dts = QTSAMPLE_DTS (stream, sample);
4960   *pts = QTSAMPLE_PTS (stream, sample);
4961   *offset = sample->offset;
4962   *size = sample->size;
4963   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4964   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4965
4966   return TRUE;
4967
4968   /* special cases */
4969 eos:
4970   {
4971     stream->time_position = GST_CLOCK_TIME_NONE;
4972     return FALSE;
4973   }
4974 }
4975
4976 /* move to the next sample in @stream.
4977  *
4978  * Moves to the next segment when needed.
4979  */
4980 static void
4981 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4982 {
4983   QtDemuxSample *sample;
4984   QtDemuxSegment *segment;
4985
4986   /* get current segment */
4987   segment = &stream->segments[stream->segment_index];
4988
4989   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4990     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4991     goto next_segment;
4992   }
4993
4994   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4995     /* Mark the stream as EOS */
4996     GST_DEBUG_OBJECT (qtdemux,
4997         "reached max allowed sample %u, mark EOS", stream->to_sample);
4998     stream->time_position = GST_CLOCK_TIME_NONE;
4999     return;
5000   }
5001
5002   /* move to next sample */
5003   stream->sample_index++;
5004   stream->offset_in_sample = 0;
5005
5006   /* reached the last sample, we need the next segment */
5007   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5008     goto next_segment;
5009
5010   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5011     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5012         stream->sample_index);
5013     return;
5014   }
5015
5016   /* get next sample */
5017   sample = &stream->samples[stream->sample_index];
5018
5019   /* see if we are past the segment */
5020   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5021     goto next_segment;
5022
5023   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5024     /* inside the segment, update time_position, looks very familiar to
5025      * GStreamer segments, doesn't it? */
5026     stream->time_position =
5027         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5028   } else {
5029     /* not yet in segment, time does not yet increment. This means
5030      * that we are still prerolling keyframes to the decoder so it can
5031      * decode the first sample of the segment. */
5032     stream->time_position = segment->time;
5033   }
5034   return;
5035
5036   /* move to the next segment */
5037 next_segment:
5038   {
5039     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5040
5041     if (stream->segment_index == stream->n_segments - 1) {
5042       /* are we at the end of the last segment, we're EOS */
5043       stream->time_position = GST_CLOCK_TIME_NONE;
5044     } else {
5045       /* else we're only at the end of the current segment */
5046       stream->time_position = segment->stop_time;
5047     }
5048     /* make sure we select a new segment */
5049
5050     /* accumulate previous segments */
5051     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5052       stream->accumulated_base +=
5053           (stream->segment.stop -
5054           stream->segment.start) / ABS (stream->segment.rate);
5055
5056     stream->segment_index = -1;
5057   }
5058 }
5059
5060 static void
5061 gst_qtdemux_sync_streams (GstQTDemux * demux)
5062 {
5063   gint i;
5064
5065   if (demux->n_streams <= 1)
5066     return;
5067
5068   for (i = 0; i < demux->n_streams; i++) {
5069     QtDemuxStream *stream;
5070     GstClockTime end_time;
5071
5072     stream = demux->streams[i];
5073
5074     if (!stream->pad)
5075       continue;
5076
5077     /* TODO advance time on subtitle streams here, if any some day */
5078
5079     /* some clips/trailers may have unbalanced streams at the end,
5080      * so send EOS on shorter stream to prevent stalling others */
5081
5082     /* do not mess with EOS if SEGMENT seeking */
5083     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5084       continue;
5085
5086     if (demux->pullbased) {
5087       /* loop mode is sample time based */
5088       if (!STREAM_IS_EOS (stream))
5089         continue;
5090     } else {
5091       /* push mode is byte position based */
5092       if (stream->n_samples &&
5093           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5094         continue;
5095     }
5096
5097     if (stream->sent_eos)
5098       continue;
5099
5100     /* only act if some gap */
5101     end_time = stream->segments[stream->n_segments - 1].stop_time;
5102     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5103         ", stream end: %" GST_TIME_FORMAT,
5104         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5105     if (GST_CLOCK_TIME_IS_VALID (end_time)
5106         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5107       GstEvent *event;
5108
5109       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5110           GST_PAD_NAME (stream->pad));
5111       stream->sent_eos = TRUE;
5112       event = gst_event_new_eos ();
5113       if (demux->segment_seqnum)
5114         gst_event_set_seqnum (event, demux->segment_seqnum);
5115       gst_pad_push_event (stream->pad, event);
5116     }
5117   }
5118 }
5119
5120 /* EOS and NOT_LINKED need to be combined. This means that we return:
5121  *
5122  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5123  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5124  */
5125 static GstFlowReturn
5126 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5127     GstFlowReturn ret)
5128 {
5129   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5130
5131   if (stream->pad)
5132     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5133         ret);
5134   else
5135     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5136
5137   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5138   return ret;
5139 }
5140
5141 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5142  * completely clipped
5143  *
5144  * Should be used only with raw buffers */
5145 static GstBuffer *
5146 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5147     GstBuffer * buf)
5148 {
5149   guint64 start, stop, cstart, cstop, diff;
5150   GstClockTime pts, duration;
5151   gsize size, osize;
5152   gint num_rate, denom_rate;
5153   gint frame_size;
5154   gboolean clip_data;
5155   guint offset;
5156
5157   osize = size = gst_buffer_get_size (buf);
5158   offset = 0;
5159
5160   /* depending on the type, setup the clip parameters */
5161   if (stream->subtype == FOURCC_soun) {
5162     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5163     num_rate = GST_SECOND;
5164     denom_rate = (gint) CUR_STREAM (stream)->rate;
5165     clip_data = TRUE;
5166   } else if (stream->subtype == FOURCC_vide) {
5167     frame_size = size;
5168     num_rate = CUR_STREAM (stream)->fps_n;
5169     denom_rate = CUR_STREAM (stream)->fps_d;
5170     clip_data = FALSE;
5171   } else
5172     goto wrong_type;
5173
5174   if (frame_size <= 0)
5175     goto bad_frame_size;
5176
5177   /* we can only clip if we have a valid pts */
5178   pts = GST_BUFFER_PTS (buf);
5179   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5180     goto no_pts;
5181
5182   duration = GST_BUFFER_DURATION (buf);
5183
5184   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5185     duration =
5186         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5187   }
5188
5189   start = pts;
5190   stop = start + duration;
5191
5192   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5193               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5194     goto clipped;
5195
5196   /* see if some clipping happened */
5197   diff = cstart - start;
5198   if (diff > 0) {
5199     pts += diff;
5200     duration -= diff;
5201
5202     if (clip_data) {
5203       /* bring clipped time to samples and to bytes */
5204       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5205       diff *= frame_size;
5206
5207       GST_DEBUG_OBJECT (qtdemux,
5208           "clipping start to %" GST_TIME_FORMAT " %"
5209           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5210
5211       offset = diff;
5212       size -= diff;
5213     }
5214   }
5215   diff = stop - cstop;
5216   if (diff > 0) {
5217     duration -= diff;
5218
5219     if (clip_data) {
5220       /* bring clipped time to samples and then to bytes */
5221       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5222       diff *= frame_size;
5223       GST_DEBUG_OBJECT (qtdemux,
5224           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5225           " bytes", GST_TIME_ARGS (cstop), diff);
5226       size -= diff;
5227     }
5228   }
5229
5230   if (offset != 0 || size != osize)
5231     gst_buffer_resize (buf, offset, size);
5232
5233   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5234   GST_BUFFER_PTS (buf) = pts;
5235   GST_BUFFER_DURATION (buf) = duration;
5236
5237   return buf;
5238
5239   /* dropped buffer */
5240 wrong_type:
5241   {
5242     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5243     return buf;
5244   }
5245 bad_frame_size:
5246   {
5247     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5248     return buf;
5249   }
5250 no_pts:
5251   {
5252     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5253     return buf;
5254   }
5255 clipped:
5256   {
5257     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5258     gst_buffer_unref (buf);
5259     return NULL;
5260   }
5261 }
5262
5263 static GstBuffer *
5264 gst_qtdemux_align_buffer (GstQTDemux * demux,
5265     GstBuffer * buffer, gsize alignment)
5266 {
5267   GstMapInfo map;
5268
5269   gst_buffer_map (buffer, &map, GST_MAP_READ);
5270
5271   if (map.size < sizeof (guintptr)) {
5272     gst_buffer_unmap (buffer, &map);
5273     return buffer;
5274   }
5275
5276   if (((guintptr) map.data) & (alignment - 1)) {
5277     GstBuffer *new_buffer;
5278     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5279
5280     new_buffer = gst_buffer_new_allocate (NULL,
5281         gst_buffer_get_size (buffer), &params);
5282
5283     /* Copy data "by hand", so ensure alignment is kept: */
5284     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5285
5286     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5287     GST_DEBUG_OBJECT (demux,
5288         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5289         alignment);
5290
5291     gst_buffer_unmap (buffer, &map);
5292     gst_buffer_unref (buffer);
5293
5294     return new_buffer;
5295   }
5296
5297   gst_buffer_unmap (buffer, &map);
5298   return buffer;
5299 }
5300
5301 /* the input buffer metadata must be writable,
5302  * but time/duration etc not yet set and need not be preserved */
5303 static GstBuffer *
5304 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5305     GstBuffer * buf)
5306 {
5307   GstMapInfo map;
5308   guint nsize = 0;
5309   gchar *str;
5310
5311   /* not many cases for now */
5312   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5313     /* send a one time dvd clut event */
5314     if (stream->pending_event && stream->pad)
5315       gst_pad_push_event (stream->pad, stream->pending_event);
5316     stream->pending_event = NULL;
5317   }
5318
5319   if (G_UNLIKELY (stream->subtype != FOURCC_text
5320           && stream->subtype != FOURCC_sbtl &&
5321           stream->subtype != FOURCC_subp)) {
5322     return buf;
5323   }
5324
5325   gst_buffer_map (buf, &map, GST_MAP_READ);
5326
5327   /* empty buffer is sent to terminate previous subtitle */
5328   if (map.size <= 2) {
5329     gst_buffer_unmap (buf, &map);
5330     gst_buffer_unref (buf);
5331     return NULL;
5332   }
5333   if (stream->subtype == FOURCC_subp) {
5334     /* That's all the processing needed for subpictures */
5335     gst_buffer_unmap (buf, &map);
5336     return buf;
5337   }
5338
5339   nsize = GST_READ_UINT16_BE (map.data);
5340   nsize = MIN (nsize, map.size - 2);
5341
5342   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5343       nsize, map.size);
5344
5345   /* takes care of UTF-8 validation or UTF-16 recognition,
5346    * no other encoding expected */
5347   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5348   gst_buffer_unmap (buf, &map);
5349   if (str) {
5350     gst_buffer_unref (buf);
5351     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5352   } else {
5353     /* this should not really happen unless the subtitle is corrupted */
5354     gst_buffer_unref (buf);
5355     buf = NULL;
5356   }
5357
5358   /* FIXME ? convert optional subsequent style info to markup */
5359
5360   return buf;
5361 }
5362
5363 /* Sets a buffer's attributes properly and pushes it downstream.
5364  * Also checks for additional actions and custom processing that may
5365  * need to be done first.
5366  */
5367 static GstFlowReturn
5368 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5369     QtDemuxStream * stream, GstBuffer * buf,
5370     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5371     gboolean keyframe, GstClockTime position, guint64 byte_position)
5372 {
5373   GstFlowReturn ret = GST_FLOW_OK;
5374
5375   /* offset the timestamps according to the edit list */
5376
5377   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5378     gchar *url;
5379     GstMapInfo map;
5380
5381     gst_buffer_map (buf, &map, GST_MAP_READ);
5382     url = g_strndup ((gchar *) map.data, map.size);
5383     gst_buffer_unmap (buf, &map);
5384     if (url != NULL && strlen (url) != 0) {
5385       /* we have RTSP redirect now */
5386       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5387           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5388               gst_structure_new ("redirect",
5389                   "new-location", G_TYPE_STRING, url, NULL)));
5390       qtdemux->posted_redirect = TRUE;
5391     } else {
5392       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5393           "posting");
5394     }
5395     g_free (url);
5396   }
5397
5398   /* position reporting */
5399   if (qtdemux->segment.rate >= 0) {
5400     qtdemux->segment.position = position;
5401     gst_qtdemux_sync_streams (qtdemux);
5402   }
5403
5404   if (G_UNLIKELY (!stream->pad)) {
5405     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5406     gst_buffer_unref (buf);
5407     goto exit;
5408   }
5409
5410   /* send out pending buffers */
5411   while (stream->buffers) {
5412     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5413
5414     if (G_UNLIKELY (stream->discont)) {
5415       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5416       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5417       stream->discont = FALSE;
5418     } else {
5419       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5420     }
5421
5422     if (stream->alignment > 1)
5423       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5424     gst_pad_push (stream->pad, buffer);
5425
5426     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5427   }
5428
5429   /* we're going to modify the metadata */
5430   buf = gst_buffer_make_writable (buf);
5431
5432   if (G_UNLIKELY (stream->need_process))
5433     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5434
5435   if (!buf) {
5436     goto exit;
5437   }
5438
5439   GST_BUFFER_DTS (buf) = dts;
5440   GST_BUFFER_PTS (buf) = pts;
5441   GST_BUFFER_DURATION (buf) = duration;
5442   GST_BUFFER_OFFSET (buf) = -1;
5443   GST_BUFFER_OFFSET_END (buf) = -1;
5444
5445   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5446     gst_buffer_append_memory (buf,
5447         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5448
5449   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5450     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5451   }
5452 #if 0
5453   if (G_UNLIKELY (qtdemux->element_index)) {
5454     GstClockTime stream_time;
5455
5456     stream_time =
5457         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5458         timestamp);
5459     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5460       GST_LOG_OBJECT (qtdemux,
5461           "adding association %" GST_TIME_FORMAT "-> %"
5462           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5463       gst_index_add_association (qtdemux->element_index,
5464           qtdemux->index_id,
5465           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5466           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5467           GST_FORMAT_BYTES, byte_position, NULL);
5468     }
5469   }
5470 #endif
5471
5472   if (stream->need_clip)
5473     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5474
5475   if (G_UNLIKELY (buf == NULL))
5476     goto exit;
5477
5478   if (G_UNLIKELY (stream->discont)) {
5479     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5480     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5481     stream->discont = FALSE;
5482   } else {
5483     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5484   }
5485
5486   if (!keyframe) {
5487     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5488     stream->on_keyframe = FALSE;
5489   } else {
5490     stream->on_keyframe = TRUE;
5491   }
5492
5493
5494   GST_LOG_OBJECT (qtdemux,
5495       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5496       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5497       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5498       GST_PAD_NAME (stream->pad));
5499
5500   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5501     GstStructure *crypto_info;
5502     QtDemuxCencSampleSetInfo *info =
5503         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5504     gint index;
5505     GstEvent *event;
5506
5507     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5508       gst_pad_push_event (stream->pad, event);
5509     }
5510
5511     if (info->crypto_info == NULL) {
5512       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5513       gst_buffer_unref (buf);
5514       goto exit;
5515     }
5516
5517     /* The end of the crypto_info array matches our n_samples position,
5518      * so count backward from there */
5519     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5520     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5521       /* steal structure from array */
5522       crypto_info = g_ptr_array_index (info->crypto_info, index);
5523       g_ptr_array_index (info->crypto_info, index) = NULL;
5524       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5525           info->crypto_info->len);
5526       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5527         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5528     } else {
5529       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5530           index, stream->sample_index);
5531     }
5532   }
5533
5534   if (stream->alignment > 1)
5535     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5536
5537   ret = gst_pad_push (stream->pad, buf);
5538
5539   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5540     /* mark position in stream, we'll need this to know when to send GAP event */
5541     stream->segment.position = pts + duration;
5542   }
5543
5544 exit:
5545   return ret;
5546 }
5547
5548 static const QtDemuxRandomAccessEntry *
5549 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5550     GstClockTime pos, gboolean after)
5551 {
5552   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5553   guint n_entries = stream->n_ra_entries;
5554   guint i;
5555
5556   /* we assume the table is sorted */
5557   for (i = 0; i < n_entries; ++i) {
5558     if (entries[i].ts > pos)
5559       break;
5560   }
5561
5562   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5563    * probably okay to assume that the index lists the very first fragment */
5564   if (i == 0)
5565     return &entries[0];
5566
5567   if (after)
5568     return &entries[i];
5569   else
5570     return &entries[i - 1];
5571 }
5572
5573 static gboolean
5574 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5575 {
5576   const QtDemuxRandomAccessEntry *best_entry = NULL;
5577   guint i;
5578
5579   GST_OBJECT_LOCK (qtdemux);
5580
5581   g_assert (qtdemux->n_streams > 0);
5582
5583   for (i = 0; i < qtdemux->n_streams; i++) {
5584     const QtDemuxRandomAccessEntry *entry;
5585     QtDemuxStream *stream;
5586     gboolean is_audio_or_video;
5587
5588     stream = qtdemux->streams[i];
5589
5590     g_free (stream->samples);
5591     stream->samples = NULL;
5592     stream->n_samples = 0;
5593     stream->stbl_index = -1;    /* no samples have yet been parsed */
5594     stream->sample_index = -1;
5595
5596     if (stream->protection_scheme_info) {
5597       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5598       if (stream->protection_scheme_type == FOURCC_cenc) {
5599         QtDemuxCencSampleSetInfo *info =
5600             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5601         if (info->crypto_info) {
5602           g_ptr_array_free (info->crypto_info, TRUE);
5603           info->crypto_info = NULL;
5604         }
5605       }
5606     }
5607
5608     if (stream->ra_entries == NULL)
5609       continue;
5610
5611     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5612       is_audio_or_video = TRUE;
5613     else
5614       is_audio_or_video = FALSE;
5615
5616     entry =
5617         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5618         stream->time_position, !is_audio_or_video);
5619
5620     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5621         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5622
5623     stream->pending_seek = entry;
5624
5625     /* decide position to jump to just based on audio/video tracks, not subs */
5626     if (!is_audio_or_video)
5627       continue;
5628
5629     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5630       best_entry = entry;
5631   }
5632
5633   if (best_entry == NULL) {
5634     GST_OBJECT_UNLOCK (qtdemux);
5635     return FALSE;
5636   }
5637
5638   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5639       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5640       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5641       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5642
5643   qtdemux->moof_offset = best_entry->moof_offset;
5644
5645   qtdemux_add_fragmented_samples (qtdemux);
5646
5647   GST_OBJECT_UNLOCK (qtdemux);
5648   return TRUE;
5649 }
5650
5651 static GstFlowReturn
5652 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5653 {
5654   GstFlowReturn ret = GST_FLOW_OK;
5655   GstBuffer *buf = NULL;
5656   QtDemuxStream *stream;
5657   GstClockTime min_time;
5658   guint64 offset = 0;
5659   GstClockTime dts = GST_CLOCK_TIME_NONE;
5660   GstClockTime pts = GST_CLOCK_TIME_NONE;
5661   GstClockTime duration = 0;
5662   gboolean keyframe = FALSE;
5663   guint sample_size = 0;
5664   gboolean empty = 0;
5665   guint size;
5666   gint index;
5667   gint i;
5668
5669   gst_qtdemux_push_pending_newsegment (qtdemux);
5670
5671   if (qtdemux->fragmented_seek_pending) {
5672     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5673     gst_qtdemux_do_fragmented_seek (qtdemux);
5674     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5675     qtdemux->fragmented_seek_pending = FALSE;
5676   }
5677
5678   /* Figure out the next stream sample to output, min_time is expressed in
5679    * global time and runs over the edit list segments. */
5680   min_time = G_MAXUINT64;
5681   index = -1;
5682   for (i = 0; i < qtdemux->n_streams; i++) {
5683     GstClockTime position;
5684
5685     stream = qtdemux->streams[i];
5686     position = stream->time_position;
5687
5688     /* position of -1 is EOS */
5689     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5690       min_time = position;
5691       index = i;
5692     }
5693   }
5694   /* all are EOS */
5695   if (G_UNLIKELY (index == -1)) {
5696     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5697     goto eos;
5698   }
5699
5700   /* check for segment end */
5701   if (G_UNLIKELY (qtdemux->segment.stop != -1
5702           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5703               || (qtdemux->segment.rate < 0
5704                   && qtdemux->segment.start > min_time))
5705           && qtdemux->streams[index]->on_keyframe)) {
5706     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5707     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5708     goto eos_stream;
5709   }
5710
5711   /* gap events for subtitle streams */
5712   for (i = 0; i < qtdemux->n_streams; i++) {
5713     stream = qtdemux->streams[i];
5714     if (stream->pad && (stream->subtype == FOURCC_subp
5715             || stream->subtype == FOURCC_text
5716             || stream->subtype == FOURCC_sbtl)) {
5717       /* send one second gap events until the stream catches up */
5718       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5719       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5720           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5721           stream->segment.position + GST_SECOND < min_time) {
5722         GstEvent *gap =
5723             gst_event_new_gap (stream->segment.position, GST_SECOND);
5724         gst_pad_push_event (stream->pad, gap);
5725         stream->segment.position += GST_SECOND;
5726       }
5727     }
5728   }
5729
5730   stream = qtdemux->streams[index];
5731   /* fetch info for the current sample of this stream */
5732   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5733               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5734     goto eos_stream;
5735
5736   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5737   if (stream->new_caps) {
5738     gst_qtdemux_configure_stream (qtdemux, stream);
5739     qtdemux_do_allocation (qtdemux, stream);
5740   }
5741
5742   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5743   if (G_UNLIKELY (qtdemux->
5744           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5745     if (stream->subtype == FOURCC_vide && !keyframe) {
5746       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5747       goto next;
5748     }
5749   }
5750
5751   GST_DEBUG_OBJECT (qtdemux,
5752       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5753       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5754       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5755       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5756
5757   if (G_UNLIKELY (empty)) {
5758     /* empty segment, push a gap and move to the next one */
5759     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5760     stream->segment.position = pts + duration;
5761     goto next;
5762   }
5763
5764   /* hmm, empty sample, skip and move to next sample */
5765   if (G_UNLIKELY (sample_size <= 0))
5766     goto next;
5767
5768   /* last pushed sample was out of boundary, goto next sample */
5769   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5770     goto next;
5771
5772   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5773     size = sample_size;
5774   } else {
5775     GST_DEBUG_OBJECT (qtdemux,
5776         "size %d larger than stream max_buffer_size %d, trimming",
5777         sample_size, stream->max_buffer_size);
5778     size =
5779         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5780   }
5781
5782   if (qtdemux->cenc_aux_info_offset > 0) {
5783     GstMapInfo map;
5784     GstByteReader br;
5785     GstBuffer *aux_info = NULL;
5786
5787     /* pull the data stored before the sample */
5788     ret =
5789         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5790         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5791     if (G_UNLIKELY (ret != GST_FLOW_OK))
5792       goto beach;
5793     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5794     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5795     gst_byte_reader_init (&br, map.data + 8, map.size);
5796     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5797             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5798       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5799       gst_buffer_unmap (aux_info, &map);
5800       gst_buffer_unref (aux_info);
5801       ret = GST_FLOW_ERROR;
5802       goto beach;
5803     }
5804     gst_buffer_unmap (aux_info, &map);
5805     gst_buffer_unref (aux_info);
5806   }
5807
5808   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5809       offset);
5810
5811   if (stream->use_allocator) {
5812     /* if we have a per-stream allocator, use it */
5813     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5814   }
5815
5816   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5817       size, &buf);
5818   if (G_UNLIKELY (ret != GST_FLOW_OK))
5819     goto beach;
5820
5821   if (size != sample_size) {
5822     pts += gst_util_uint64_scale_int (GST_SECOND,
5823         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5824         stream->timescale);
5825     dts +=
5826         gst_util_uint64_scale_int (GST_SECOND,
5827         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5828         stream->timescale);
5829     duration =
5830         gst_util_uint64_scale_int (GST_SECOND,
5831         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5832   }
5833
5834   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5835       dts, pts, duration, keyframe, min_time, offset);
5836
5837   if (size != sample_size) {
5838     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5839     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5840
5841     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5842         sample->timestamp +
5843         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5844     if (time_position >= segment->media_start) {
5845       /* inside the segment, update time_position, looks very familiar to
5846        * GStreamer segments, doesn't it? */
5847       stream->time_position = (time_position - segment->media_start) +
5848           segment->time;
5849     } else {
5850       /* not yet in segment, time does not yet increment. This means
5851        * that we are still prerolling keyframes to the decoder so it can
5852        * decode the first sample of the segment. */
5853       stream->time_position = segment->time;
5854     }
5855   }
5856
5857   /* combine flows */
5858   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5859   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5860    * we have no more data for the pad to push */
5861   if (ret == GST_FLOW_EOS)
5862     ret = GST_FLOW_OK;
5863
5864   stream->offset_in_sample += size;
5865   if (stream->offset_in_sample >= sample_size) {
5866     gst_qtdemux_advance_sample (qtdemux, stream);
5867   }
5868   goto beach;
5869
5870 next:
5871   gst_qtdemux_advance_sample (qtdemux, stream);
5872
5873 beach:
5874   return ret;
5875
5876   /* special cases */
5877 eos:
5878   {
5879     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5880     ret = GST_FLOW_EOS;
5881     goto beach;
5882   }
5883 eos_stream:
5884   {
5885     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5886     /* EOS will be raised if all are EOS */
5887     ret = GST_FLOW_OK;
5888     goto beach;
5889   }
5890 }
5891
5892 static void
5893 gst_qtdemux_loop (GstPad * pad)
5894 {
5895   GstQTDemux *qtdemux;
5896   guint64 cur_offset;
5897   GstFlowReturn ret;
5898
5899   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5900
5901   cur_offset = qtdemux->offset;
5902   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5903       cur_offset, qt_demux_state_string (qtdemux->state));
5904
5905   switch (qtdemux->state) {
5906     case QTDEMUX_STATE_INITIAL:
5907     case QTDEMUX_STATE_HEADER:
5908       ret = gst_qtdemux_loop_state_header (qtdemux);
5909       break;
5910     case QTDEMUX_STATE_MOVIE:
5911       ret = gst_qtdemux_loop_state_movie (qtdemux);
5912       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5913         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5914       }
5915       break;
5916     default:
5917       /* ouch */
5918       goto invalid_state;
5919   }
5920
5921   /* if something went wrong, pause */
5922   if (ret != GST_FLOW_OK)
5923     goto pause;
5924
5925 done:
5926   gst_object_unref (qtdemux);
5927   return;
5928
5929   /* ERRORS */
5930 invalid_state:
5931   {
5932     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5933         (NULL), ("streaming stopped, invalid state"));
5934     gst_pad_pause_task (pad);
5935     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5936     goto done;
5937   }
5938 pause:
5939   {
5940     const gchar *reason = gst_flow_get_name (ret);
5941
5942     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5943
5944     gst_pad_pause_task (pad);
5945
5946     /* fatal errors need special actions */
5947     /* check EOS */
5948     if (ret == GST_FLOW_EOS) {
5949       if (qtdemux->n_streams == 0) {
5950         /* we have no streams, post an error */
5951         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5952       }
5953       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5954         gint64 stop;
5955
5956         if ((stop = qtdemux->segment.stop) == -1)
5957           stop = qtdemux->segment.duration;
5958
5959         if (qtdemux->segment.rate >= 0) {
5960           GstMessage *message;
5961           GstEvent *event;
5962
5963           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5964           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5965               GST_FORMAT_TIME, stop);
5966           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5967           if (qtdemux->segment_seqnum) {
5968             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5969             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5970           }
5971           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5972           gst_qtdemux_push_event (qtdemux, event);
5973         } else {
5974           GstMessage *message;
5975           GstEvent *event;
5976
5977           /*  For Reverse Playback */
5978           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5979           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5980               GST_FORMAT_TIME, qtdemux->segment.start);
5981           event = gst_event_new_segment_done (GST_FORMAT_TIME,
5982               qtdemux->segment.start);
5983           if (qtdemux->segment_seqnum) {
5984             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5985             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5986           }
5987           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5988           gst_qtdemux_push_event (qtdemux, event);
5989         }
5990       } else {
5991         GstEvent *event;
5992
5993         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5994         event = gst_event_new_eos ();
5995         if (qtdemux->segment_seqnum)
5996           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5997         gst_qtdemux_push_event (qtdemux, event);
5998       }
5999     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6000       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6001       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6002     }
6003     goto done;
6004   }
6005 }
6006
6007 /*
6008  * has_next_entry
6009  *
6010  * Returns if there are samples to be played.
6011  */
6012 static gboolean
6013 has_next_entry (GstQTDemux * demux)
6014 {
6015   QtDemuxStream *stream;
6016   int i;
6017
6018   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6019
6020   for (i = 0; i < demux->n_streams; i++) {
6021     stream = demux->streams[i];
6022
6023     if (stream->sample_index == -1) {
6024       stream->sample_index = 0;
6025       stream->offset_in_sample = 0;
6026     }
6027
6028     if (stream->sample_index >= stream->n_samples) {
6029       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6030       continue;
6031     }
6032     GST_DEBUG_OBJECT (demux, "Found a sample");
6033     return TRUE;
6034   }
6035
6036   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6037   return FALSE;
6038 }
6039
6040 /*
6041  * next_entry_size
6042  *
6043  * Returns the size of the first entry at the current offset.
6044  * If -1, there are none (which means EOS or empty file).
6045  */
6046 static guint64
6047 next_entry_size (GstQTDemux * demux)
6048 {
6049   QtDemuxStream *stream;
6050   int i;
6051   int smallidx = -1;
6052   guint64 smalloffs = (guint64) - 1;
6053   QtDemuxSample *sample;
6054
6055   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6056       demux->offset);
6057
6058   for (i = 0; i < demux->n_streams; i++) {
6059     stream = demux->streams[i];
6060
6061     if (stream->sample_index == -1) {
6062       stream->sample_index = 0;
6063       stream->offset_in_sample = 0;
6064     }
6065
6066     if (stream->sample_index >= stream->n_samples) {
6067       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6068       continue;
6069     }
6070
6071     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6072       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6073           stream->sample_index);
6074       return -1;
6075     }
6076
6077     sample = &stream->samples[stream->sample_index];
6078
6079     GST_LOG_OBJECT (demux,
6080         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6081         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6082         sample->offset, sample->size);
6083
6084     if (((smalloffs == -1)
6085             || (sample->offset < smalloffs)) && (sample->size)) {
6086       smallidx = i;
6087       smalloffs = sample->offset;
6088     }
6089   }
6090
6091   GST_LOG_OBJECT (demux,
6092       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6093       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6094
6095   if (smallidx == -1)
6096     return -1;
6097
6098   stream = demux->streams[smallidx];
6099   sample = &stream->samples[stream->sample_index];
6100
6101   if (sample->offset >= demux->offset) {
6102     demux->todrop = sample->offset - demux->offset;
6103     return sample->size + demux->todrop;
6104   }
6105
6106   GST_DEBUG_OBJECT (demux,
6107       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6108   return -1;
6109 }
6110
6111 static void
6112 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6113 {
6114   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6115
6116   gst_element_post_message (GST_ELEMENT_CAST (demux),
6117       gst_message_new_element (GST_OBJECT_CAST (demux),
6118           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6119 }
6120
6121 static gboolean
6122 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6123 {
6124   GstEvent *event;
6125   gboolean res = 0;
6126
6127   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6128
6129   event =
6130       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6131       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6132       GST_SEEK_TYPE_NONE, -1);
6133
6134   /* store seqnum to drop flush events, they don't need to reach downstream */
6135   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6136   res = gst_pad_push_event (demux->sinkpad, event);
6137   demux->offset_seek_seqnum = 0;
6138
6139   return res;
6140 }
6141
6142 /* check for seekable upstream, above and beyond a mere query */
6143 static void
6144 gst_qtdemux_check_seekability (GstQTDemux * demux)
6145 {
6146   GstQuery *query;
6147   gboolean seekable = FALSE;
6148   gint64 start = -1, stop = -1;
6149
6150   if (demux->upstream_size)
6151     return;
6152
6153   if (demux->upstream_format_is_time)
6154     return;
6155
6156   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6157   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6158     GST_DEBUG_OBJECT (demux, "seeking query failed");
6159     goto done;
6160   }
6161
6162   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6163
6164   /* try harder to query upstream size if we didn't get it the first time */
6165   if (seekable && stop == -1) {
6166     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6167     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6168   }
6169
6170   /* if upstream doesn't know the size, it's likely that it's not seekable in
6171    * practice even if it technically may be seekable */
6172   if (seekable && (start != 0 || stop <= start)) {
6173     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6174     seekable = FALSE;
6175   }
6176
6177 done:
6178   gst_query_unref (query);
6179
6180   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6181       G_GUINT64_FORMAT ")", seekable, start, stop);
6182   demux->upstream_seekable = seekable;
6183   demux->upstream_size = seekable ? stop : -1;
6184 }
6185
6186 static void
6187 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6188 {
6189   g_return_if_fail (bytes <= demux->todrop);
6190
6191   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6192   gst_adapter_flush (demux->adapter, bytes);
6193   demux->neededbytes -= bytes;
6194   demux->offset += bytes;
6195   demux->todrop -= bytes;
6196 }
6197
6198 static void
6199 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6200 {
6201   if (G_UNLIKELY (demux->pending_newsegment)) {
6202     gint i;
6203
6204     gst_qtdemux_push_pending_newsegment (demux);
6205     /* clear to send tags on all streams */
6206     for (i = 0; i < demux->n_streams; i++) {
6207       QtDemuxStream *stream;
6208       stream = demux->streams[i];
6209       gst_qtdemux_push_tags (demux, stream);
6210       if (CUR_STREAM (stream)->sparse) {
6211         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6212         gst_pad_push_event (stream->pad,
6213             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6214       }
6215     }
6216   }
6217 }
6218
6219 static void
6220 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6221     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6222 {
6223   GstClockTime ts, dur;
6224   GstEvent *gap;
6225
6226   ts = pos;
6227   dur =
6228       stream->segments[segment_index].duration - (pos -
6229       stream->segments[segment_index].time);
6230   gap = gst_event_new_gap (ts, dur);
6231   stream->time_position += dur;
6232
6233   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6234       "segment: %" GST_PTR_FORMAT, gap);
6235   gst_pad_push_event (stream->pad, gap);
6236 }
6237
6238 static void
6239 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6240     QtDemuxStream * stream)
6241 {
6242   gint i;
6243
6244   /* Push any initial gap segments before proceeding to the
6245    * 'real' data */
6246   for (i = 0; i < stream->n_segments; i++) {
6247     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6248
6249     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6250       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6251           stream->time_position);
6252     } else {
6253       /* Only support empty segment at the beginning followed by
6254        * one non-empty segment, this was checked when parsing the
6255        * edts atom, arriving here is unexpected */
6256       g_assert (i + 1 == stream->n_segments);
6257       break;
6258     }
6259   }
6260 }
6261
6262 static GstFlowReturn
6263 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6264 {
6265   GstQTDemux *demux;
6266
6267   demux = GST_QTDEMUX (parent);
6268
6269   GST_DEBUG_OBJECT (demux,
6270       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6271       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6272       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6273       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6274       gst_buffer_get_size (inbuf), demux->offset);
6275
6276   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6277     gboolean is_gap_input = FALSE;
6278     gint i;
6279
6280     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6281
6282     for (i = 0; i < demux->n_streams; i++) {
6283       demux->streams[i]->discont = TRUE;
6284     }
6285
6286     /* Check if we can land back on our feet in the case where upstream is
6287      * handling the seeking/pushing of samples with gaps in between (like
6288      * in the case of trick-mode DASH for example) */
6289     if (demux->upstream_format_is_time
6290         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6291       gint i;
6292       for (i = 0; i < demux->n_streams; i++) {
6293         guint32 res;
6294         GST_LOG_OBJECT (demux,
6295             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6296             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6297         res =
6298             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6299             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6300         if (res != -1) {
6301           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6302           GST_LOG_OBJECT (demux,
6303               "Checking if sample %d from stream %d is valid (offset:%"
6304               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6305               sample->offset, sample->size);
6306           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6307             GST_LOG_OBJECT (demux,
6308                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6309                 res);
6310             is_gap_input = TRUE;
6311             /* We can go back to standard playback mode */
6312             demux->state = QTDEMUX_STATE_MOVIE;
6313             /* Remember which sample this stream is at */
6314             demux->streams[i]->sample_index = res;
6315             /* Finally update all push-based values to the expected values */
6316             demux->neededbytes = demux->streams[i]->samples[res].size;
6317             demux->offset = GST_BUFFER_OFFSET (inbuf);
6318             demux->mdatleft =
6319                 demux->mdatsize - demux->offset + demux->mdatoffset;
6320             demux->todrop = 0;
6321           }
6322         }
6323       }
6324       if (!is_gap_input) {
6325         /* Reset state if it's a real discont */
6326         demux->neededbytes = 16;
6327         demux->state = QTDEMUX_STATE_INITIAL;
6328         demux->offset = GST_BUFFER_OFFSET (inbuf);
6329       }
6330     }
6331     /* Reverse fragmented playback, need to flush all we have before
6332      * consuming a new fragment.
6333      * The samples array have the timestamps calculated by accumulating the
6334      * durations but this won't work for reverse playback of fragments as
6335      * the timestamps of a subsequent fragment should be smaller than the
6336      * previously received one. */
6337     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6338       gst_qtdemux_process_adapter (demux, TRUE);
6339       for (i = 0; i < demux->n_streams; i++)
6340         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6341     }
6342   }
6343
6344   gst_adapter_push (demux->adapter, inbuf);
6345
6346   GST_DEBUG_OBJECT (demux,
6347       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6348       demux->neededbytes, gst_adapter_available (demux->adapter));
6349
6350   return gst_qtdemux_process_adapter (demux, FALSE);
6351 }
6352
6353 static GstFlowReturn
6354 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6355 {
6356   GstFlowReturn ret = GST_FLOW_OK;
6357
6358   /* we never really mean to buffer that much */
6359   if (demux->neededbytes == -1) {
6360     goto eos;
6361   }
6362
6363   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6364       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6365
6366 #ifndef GST_DISABLE_GST_DEBUG
6367     {
6368       guint64 discont_offset, distance_from_discont;
6369
6370       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6371       distance_from_discont =
6372           gst_adapter_distance_from_discont (demux->adapter);
6373
6374       GST_DEBUG_OBJECT (demux,
6375           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6376           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6377           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6378           demux->offset, discont_offset, distance_from_discont);
6379     }
6380 #endif
6381
6382     switch (demux->state) {
6383       case QTDEMUX_STATE_INITIAL:{
6384         const guint8 *data;
6385         guint32 fourcc;
6386         guint64 size;
6387
6388         gst_qtdemux_check_seekability (demux);
6389
6390         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6391
6392         /* get fourcc/length, set neededbytes */
6393         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6394             &size, &fourcc);
6395         gst_adapter_unmap (demux->adapter);
6396         data = NULL;
6397         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6398             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6399         if (size == 0) {
6400           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6401               (_("This file is invalid and cannot be played.")),
6402               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6403                   GST_FOURCC_ARGS (fourcc)));
6404           ret = GST_FLOW_ERROR;
6405           break;
6406         }
6407         if (fourcc == FOURCC_mdat) {
6408           gint next_entry = next_entry_size (demux);
6409           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6410             /* we have the headers, start playback */
6411             demux->state = QTDEMUX_STATE_MOVIE;
6412             demux->neededbytes = next_entry;
6413             demux->mdatleft = size;
6414             demux->mdatsize = demux->mdatleft;
6415           } else {
6416             /* no headers yet, try to get them */
6417             guint bs;
6418             gboolean res;
6419             guint64 old, target;
6420
6421           buffer_data:
6422             old = demux->offset;
6423             target = old + size;
6424
6425             /* try to jump over the atom with a seek */
6426             /* only bother if it seems worth doing so,
6427              * and avoids possible upstream/server problems */
6428             if (demux->upstream_seekable &&
6429                 demux->upstream_size > 4 * (1 << 20)) {
6430               res = qtdemux_seek_offset (demux, target);
6431             } else {
6432               GST_DEBUG_OBJECT (demux, "skipping seek");
6433               res = FALSE;
6434             }
6435
6436             if (res) {
6437               GST_DEBUG_OBJECT (demux, "seek success");
6438               /* remember the offset fo the first mdat so we can seek back to it
6439                * after we have the headers */
6440               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6441                 demux->first_mdat = old;
6442                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6443                     demux->first_mdat);
6444               }
6445               /* seek worked, continue reading */
6446               demux->offset = target;
6447               demux->neededbytes = 16;
6448               demux->state = QTDEMUX_STATE_INITIAL;
6449             } else {
6450               /* seek failed, need to buffer */
6451               demux->offset = old;
6452               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6453               /* there may be multiple mdat (or alike) buffers */
6454               /* sanity check */
6455               if (demux->mdatbuffer)
6456                 bs = gst_buffer_get_size (demux->mdatbuffer);
6457               else
6458                 bs = 0;
6459               if (size + bs > 10 * (1 << 20))
6460                 goto no_moov;
6461               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6462               demux->neededbytes = size;
6463               if (!demux->mdatbuffer)
6464                 demux->mdatoffset = demux->offset;
6465             }
6466           }
6467         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6468           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6469               (_("This file is invalid and cannot be played.")),
6470               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6471                   GST_FOURCC_ARGS (fourcc), size));
6472           ret = GST_FLOW_ERROR;
6473           break;
6474         } else {
6475           /* this means we already started buffering and still no moov header,
6476            * let's continue buffering everything till we get moov */
6477           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6478                   || fourcc == FOURCC_moof))
6479             goto buffer_data;
6480           demux->neededbytes = size;
6481           demux->state = QTDEMUX_STATE_HEADER;
6482         }
6483         break;
6484       }
6485       case QTDEMUX_STATE_HEADER:{
6486         const guint8 *data;
6487         guint32 fourcc;
6488
6489         GST_DEBUG_OBJECT (demux, "In header");
6490
6491         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6492
6493         /* parse the header */
6494         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6495             &fourcc);
6496         if (fourcc == FOURCC_moov) {
6497           gint n;
6498
6499           /* in usual fragmented setup we could try to scan for more
6500            * and end up at the the moov (after mdat) again */
6501           if (demux->got_moov && demux->n_streams > 0 &&
6502               (!demux->fragmented
6503                   || demux->last_moov_offset == demux->offset)) {
6504             GST_DEBUG_OBJECT (demux,
6505                 "Skipping moov atom as we have (this) one already");
6506           } else {
6507             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6508
6509             if (demux->got_moov && demux->fragmented) {
6510               GST_DEBUG_OBJECT (demux,
6511                   "Got a second moov, clean up data from old one");
6512               if (demux->moov_node_compressed) {
6513                 g_node_destroy (demux->moov_node_compressed);
6514                 if (demux->moov_node)
6515                   g_free (demux->moov_node->data);
6516               }
6517               demux->moov_node_compressed = NULL;
6518               if (demux->moov_node)
6519                 g_node_destroy (demux->moov_node);
6520               demux->moov_node = NULL;
6521             } else {
6522               /* prepare newsegment to send when streaming actually starts */
6523               if (!demux->pending_newsegment) {
6524                 demux->pending_newsegment =
6525                     gst_event_new_segment (&demux->segment);
6526                 if (demux->segment_seqnum)
6527                   gst_event_set_seqnum (demux->pending_newsegment,
6528                       demux->segment_seqnum);
6529               }
6530             }
6531
6532             demux->last_moov_offset = demux->offset;
6533
6534             qtdemux_parse_moov (demux, data, demux->neededbytes);
6535             qtdemux_node_dump (demux, demux->moov_node);
6536             qtdemux_parse_tree (demux);
6537             qtdemux_prepare_streams (demux);
6538             if (!demux->got_moov)
6539               qtdemux_expose_streams (demux);
6540             else {
6541
6542               for (n = 0; n < demux->n_streams; n++) {
6543                 QtDemuxStream *stream = demux->streams[n];
6544
6545                 gst_qtdemux_configure_stream (demux, stream);
6546               }
6547             }
6548
6549             demux->got_moov = TRUE;
6550             gst_qtdemux_check_send_pending_segment (demux);
6551
6552             /* fragmented streams headers shouldn't contain edts atoms */
6553             if (!demux->fragmented) {
6554               for (n = 0; n < demux->n_streams; n++) {
6555                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6556                     demux->streams[n]);
6557               }
6558             }
6559
6560             if (demux->moov_node_compressed) {
6561               g_node_destroy (demux->moov_node_compressed);
6562               g_free (demux->moov_node->data);
6563             }
6564             demux->moov_node_compressed = NULL;
6565             g_node_destroy (demux->moov_node);
6566             demux->moov_node = NULL;
6567             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6568           }
6569         } else if (fourcc == FOURCC_moof) {
6570           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6571             guint64 dist = 0;
6572             GstClockTime prev_pts;
6573             guint64 prev_offset;
6574             guint64 adapter_discont_offset, adapter_discont_dist;
6575
6576             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6577
6578             /*
6579              * The timestamp of the moof buffer is relevant as some scenarios
6580              * won't have the initial timestamp in the atoms. Whenever a new
6581              * buffer has started, we get that buffer's PTS and use it as a base
6582              * timestamp for the trun entries.
6583              *
6584              * To keep track of the current buffer timestamp and starting point
6585              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6586              * from the beggining of the buffer, with the distance and demux->offset
6587              * we know if it is still the same buffer or not.
6588              */
6589             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6590             prev_offset = demux->offset - dist;
6591             if (demux->fragment_start_offset == -1
6592                 || prev_offset > demux->fragment_start_offset) {
6593               demux->fragment_start_offset = prev_offset;
6594               demux->fragment_start = prev_pts;
6595               GST_DEBUG_OBJECT (demux,
6596                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6597                   GST_TIME_FORMAT, demux->fragment_start_offset,
6598                   GST_TIME_ARGS (demux->fragment_start));
6599             }
6600
6601             /* We can't use prev_offset() here because this would require
6602              * upstream to set consistent and correct offsets on all buffers
6603              * since the discont. Nothing ever did that in the past and we
6604              * would break backwards compatibility here then.
6605              * Instead take the offset we had at the last discont and count
6606              * the bytes from there. This works with old code as there would
6607              * be no discont between moov and moof, and also works with
6608              * adaptivedemux which correctly sets offset and will set the
6609              * DISCONT flag accordingly when needed.
6610              *
6611              * We also only do this for upstream TIME segments as otherwise
6612              * there are potential backwards compatibility problems with
6613              * seeking in PUSH mode and upstream providing inconsistent
6614              * timestamps. */
6615             adapter_discont_offset =
6616                 gst_adapter_offset_at_discont (demux->adapter);
6617             adapter_discont_dist =
6618                 gst_adapter_distance_from_discont (demux->adapter);
6619
6620             GST_DEBUG_OBJECT (demux,
6621                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6622                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6623                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6624
6625             if (demux->upstream_format_is_time) {
6626               demux->moof_offset = adapter_discont_offset;
6627               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6628                 demux->moof_offset += adapter_discont_dist;
6629               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6630                 demux->moof_offset = demux->offset;
6631             } else {
6632               demux->moof_offset = demux->offset;
6633             }
6634
6635             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6636                     demux->moof_offset, NULL)) {
6637               gst_adapter_unmap (demux->adapter);
6638               ret = GST_FLOW_ERROR;
6639               goto done;
6640             }
6641             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6642             if (demux->mss_mode && !demux->exposed) {
6643               if (!demux->pending_newsegment) {
6644                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6645                 demux->pending_newsegment =
6646                     gst_event_new_segment (&demux->segment);
6647                 if (demux->segment_seqnum)
6648                   gst_event_set_seqnum (demux->pending_newsegment,
6649                       demux->segment_seqnum);
6650               }
6651               qtdemux_expose_streams (demux);
6652             }
6653           } else {
6654             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6655           }
6656         } else if (fourcc == FOURCC_ftyp) {
6657           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6658           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6659         } else if (fourcc == FOURCC_uuid) {
6660           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6661           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6662         } else if (fourcc == FOURCC_sidx) {
6663           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6664           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6665         } else {
6666           switch (fourcc) {
6667             case FOURCC_styp:
6668               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6669                * FALLTHROUGH */
6670             case FOURCC_free:
6671               /* [free] is a padding atom */
6672               GST_DEBUG_OBJECT (demux,
6673                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6674                   GST_FOURCC_ARGS (fourcc));
6675               break;
6676             default:
6677               GST_WARNING_OBJECT (demux,
6678                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6679                   GST_FOURCC_ARGS (fourcc));
6680               /* Let's jump that one and go back to initial state */
6681               break;
6682           }
6683         }
6684         gst_adapter_unmap (demux->adapter);
6685         data = NULL;
6686
6687         if (demux->mdatbuffer && demux->n_streams) {
6688           gsize remaining_data_size = 0;
6689
6690           /* the mdat was before the header */
6691           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6692               demux->n_streams, demux->mdatbuffer);
6693           /* restore our adapter/offset view of things with upstream;
6694            * put preceding buffered data ahead of current moov data.
6695            * This should also handle evil mdat, moov, mdat cases and alike */
6696           gst_adapter_flush (demux->adapter, demux->neededbytes);
6697
6698           /* Store any remaining data after the mdat for later usage */
6699           remaining_data_size = gst_adapter_available (demux->adapter);
6700           if (remaining_data_size > 0) {
6701             g_assert (demux->restoredata_buffer == NULL);
6702             demux->restoredata_buffer =
6703                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6704             demux->restoredata_offset = demux->offset + demux->neededbytes;
6705             GST_DEBUG_OBJECT (demux,
6706                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6707                 G_GUINT64_FORMAT, remaining_data_size,
6708                 demux->restoredata_offset);
6709           }
6710
6711           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6712           demux->mdatbuffer = NULL;
6713           demux->offset = demux->mdatoffset;
6714           demux->neededbytes = next_entry_size (demux);
6715           demux->state = QTDEMUX_STATE_MOVIE;
6716           demux->mdatleft = gst_adapter_available (demux->adapter);
6717           demux->mdatsize = demux->mdatleft;
6718         } else {
6719           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6720           gst_adapter_flush (demux->adapter, demux->neededbytes);
6721
6722           /* only go back to the mdat if there are samples to play */
6723           if (demux->got_moov && demux->first_mdat != -1
6724               && has_next_entry (demux)) {
6725             gboolean res;
6726
6727             /* we need to seek back */
6728             res = qtdemux_seek_offset (demux, demux->first_mdat);
6729             if (res) {
6730               demux->offset = demux->first_mdat;
6731             } else {
6732               GST_DEBUG_OBJECT (demux, "Seek back failed");
6733             }
6734           } else {
6735             demux->offset += demux->neededbytes;
6736           }
6737           demux->neededbytes = 16;
6738           demux->state = QTDEMUX_STATE_INITIAL;
6739         }
6740
6741         break;
6742       }
6743       case QTDEMUX_STATE_BUFFER_MDAT:{
6744         GstBuffer *buf;
6745         guint8 fourcc[4];
6746
6747         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6748             demux->offset);
6749         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6750         gst_buffer_extract (buf, 0, fourcc, 4);
6751         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6752             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6753         if (demux->mdatbuffer)
6754           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6755         else
6756           demux->mdatbuffer = buf;
6757         demux->offset += demux->neededbytes;
6758         demux->neededbytes = 16;
6759         demux->state = QTDEMUX_STATE_INITIAL;
6760         gst_qtdemux_post_progress (demux, 1, 1);
6761
6762         break;
6763       }
6764       case QTDEMUX_STATE_MOVIE:{
6765         QtDemuxStream *stream = NULL;
6766         QtDemuxSample *sample;
6767         int i = -1;
6768         GstClockTime dts, pts, duration;
6769         gboolean keyframe;
6770
6771         GST_DEBUG_OBJECT (demux,
6772             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6773
6774         if (demux->fragmented) {
6775           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6776               demux->mdatleft);
6777           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6778             /* if needed data starts within this atom,
6779              * then it should not exceed this atom */
6780             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6781               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6782                   (_("This file is invalid and cannot be played.")),
6783                   ("sample data crosses atom boundary"));
6784               ret = GST_FLOW_ERROR;
6785               break;
6786             }
6787             demux->mdatleft -= demux->neededbytes;
6788           } else {
6789             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6790             /* so we are dropping more than left in this atom */
6791             gst_qtdemux_drop_data (demux, demux->mdatleft);
6792             demux->mdatleft = 0;
6793
6794             /* need to resume atom parsing so we do not miss any other pieces */
6795             demux->state = QTDEMUX_STATE_INITIAL;
6796             demux->neededbytes = 16;
6797
6798             /* check if there was any stored post mdat data from previous buffers */
6799             if (demux->restoredata_buffer) {
6800               g_assert (gst_adapter_available (demux->adapter) == 0);
6801
6802               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6803               demux->restoredata_buffer = NULL;
6804               demux->offset = demux->restoredata_offset;
6805             }
6806
6807             break;
6808           }
6809         }
6810
6811         if (demux->todrop) {
6812           if (demux->cenc_aux_info_offset > 0) {
6813             GstByteReader br;
6814             const guint8 *data;
6815
6816             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6817             data = gst_adapter_map (demux->adapter, demux->todrop);
6818             gst_byte_reader_init (&br, data + 8, demux->todrop);
6819             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6820                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6821               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6822               ret = GST_FLOW_ERROR;
6823               gst_adapter_unmap (demux->adapter);
6824               g_free (demux->cenc_aux_info_sizes);
6825               demux->cenc_aux_info_sizes = NULL;
6826               goto done;
6827             }
6828             demux->cenc_aux_info_offset = 0;
6829             g_free (demux->cenc_aux_info_sizes);
6830             demux->cenc_aux_info_sizes = NULL;
6831             gst_adapter_unmap (demux->adapter);
6832           }
6833           gst_qtdemux_drop_data (demux, demux->todrop);
6834         }
6835
6836         /* first buffer? */
6837         /* initial newsegment sent here after having added pads,
6838          * possible others in sink_event */
6839         gst_qtdemux_check_send_pending_segment (demux);
6840
6841         /* Figure out which stream this packet belongs to */
6842         for (i = 0; i < demux->n_streams; i++) {
6843           stream = demux->streams[i];
6844           if (stream->sample_index >= stream->n_samples)
6845             continue;
6846           GST_LOG_OBJECT (demux,
6847               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6848               " / size:%d)", i, stream->sample_index,
6849               stream->samples[stream->sample_index].offset,
6850               stream->samples[stream->sample_index].size);
6851
6852           if (stream->samples[stream->sample_index].offset == demux->offset)
6853             break;
6854         }
6855
6856         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6857           goto unknown_stream;
6858
6859         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6860
6861         if (stream->new_caps) {
6862           gst_qtdemux_configure_stream (demux, stream);
6863         }
6864
6865         /* Put data in a buffer, set timestamps, caps, ... */
6866         sample = &stream->samples[stream->sample_index];
6867
6868         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6869           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6870               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6871
6872           dts = QTSAMPLE_DTS (stream, sample);
6873           pts = QTSAMPLE_PTS (stream, sample);
6874           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6875           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6876
6877           /* check for segment end */
6878           if (G_UNLIKELY (demux->segment.stop != -1
6879                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6880             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6881             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6882
6883             /* skip this data, stream is EOS */
6884             gst_adapter_flush (demux->adapter, demux->neededbytes);
6885
6886             /* check if all streams are eos */
6887             ret = GST_FLOW_EOS;
6888             for (i = 0; i < demux->n_streams; i++) {
6889               if (!STREAM_IS_EOS (demux->streams[i])) {
6890                 ret = GST_FLOW_OK;
6891                 break;
6892               }
6893             }
6894
6895             if (ret == GST_FLOW_EOS) {
6896               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6897               goto eos;
6898             }
6899           } else {
6900             GstBuffer *outbuf;
6901
6902             outbuf =
6903                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6904
6905             /* FIXME: should either be an assert or a plain check */
6906             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6907
6908             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6909                 dts, pts, duration, keyframe, dts, demux->offset);
6910           }
6911
6912           /* combine flows */
6913           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6914         } else {
6915           /* skip this data, stream is EOS */
6916           gst_adapter_flush (demux->adapter, demux->neededbytes);
6917         }
6918
6919         stream->sample_index++;
6920         stream->offset_in_sample = 0;
6921
6922         /* update current offset and figure out size of next buffer */
6923         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6924             demux->offset, demux->neededbytes);
6925         demux->offset += demux->neededbytes;
6926         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6927             demux->offset);
6928
6929         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6930           if (demux->fragmented) {
6931             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6932             /* there may be more to follow, only finish this atom */
6933             demux->todrop = demux->mdatleft;
6934             demux->neededbytes = demux->todrop;
6935             break;
6936           }
6937           goto eos;
6938         }
6939         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6940           goto non_ok_unlinked_flow;
6941         }
6942         break;
6943       }
6944       default:
6945         goto invalid_state;
6946     }
6947   }
6948
6949   /* when buffering movie data, at least show user something is happening */
6950   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6951       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6952     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6953         demux->neededbytes);
6954   }
6955 done:
6956
6957   return ret;
6958
6959   /* ERRORS */
6960 non_ok_unlinked_flow:
6961   {
6962     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6963         gst_flow_get_name (ret));
6964     return ret;
6965   }
6966 unknown_stream:
6967   {
6968     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6969     ret = GST_FLOW_ERROR;
6970     goto done;
6971   }
6972 eos:
6973   {
6974     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6975     ret = GST_FLOW_EOS;
6976     goto done;
6977   }
6978 invalid_state:
6979   {
6980     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6981         (NULL), ("qtdemuxer invalid state %d", demux->state));
6982     ret = GST_FLOW_ERROR;
6983     goto done;
6984   }
6985 no_moov:
6986   {
6987     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6988         (NULL), ("no 'moov' atom within the first 10 MB"));
6989     ret = GST_FLOW_ERROR;
6990     goto done;
6991   }
6992 }
6993
6994 static gboolean
6995 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6996 {
6997   GstQuery *query;
6998   gboolean pull_mode;
6999
7000   query = gst_query_new_scheduling ();
7001
7002   if (!gst_pad_peer_query (sinkpad, query)) {
7003     gst_query_unref (query);
7004     goto activate_push;
7005   }
7006
7007   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7008       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7009   gst_query_unref (query);
7010
7011   if (!pull_mode)
7012     goto activate_push;
7013
7014   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7015   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7016
7017 activate_push:
7018   {
7019     GST_DEBUG_OBJECT (sinkpad, "activating push");
7020     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7021   }
7022 }
7023
7024 static gboolean
7025 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7026     GstPadMode mode, gboolean active)
7027 {
7028   gboolean res;
7029   GstQTDemux *demux = GST_QTDEMUX (parent);
7030
7031   switch (mode) {
7032     case GST_PAD_MODE_PUSH:
7033       demux->pullbased = FALSE;
7034       res = TRUE;
7035       break;
7036     case GST_PAD_MODE_PULL:
7037       if (active) {
7038         demux->pullbased = TRUE;
7039         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7040             sinkpad, NULL);
7041       } else {
7042         res = gst_pad_stop_task (sinkpad);
7043       }
7044       break;
7045     default:
7046       res = FALSE;
7047       break;
7048   }
7049   return res;
7050 }
7051
7052 #ifdef HAVE_ZLIB
7053 static void *
7054 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7055 {
7056   guint8 *buffer;
7057   z_stream z;
7058   int ret;
7059
7060   memset (&z, 0, sizeof (z));
7061   z.zalloc = NULL;
7062   z.zfree = NULL;
7063   z.opaque = NULL;
7064
7065   if ((ret = inflateInit (&z)) != Z_OK) {
7066     GST_ERROR ("inflateInit() returned %d", ret);
7067     return NULL;
7068   }
7069
7070   z.next_in = z_buffer;
7071   z.avail_in = z_length;
7072
7073   buffer = (guint8 *) g_malloc (*length);
7074   z.avail_out = *length;
7075   z.next_out = (Bytef *) buffer;
7076   do {
7077     ret = inflate (&z, Z_NO_FLUSH);
7078     if (ret == Z_STREAM_END) {
7079       break;
7080     } else if (ret != Z_OK) {
7081       GST_WARNING ("inflate() returned %d", ret);
7082       break;
7083     }
7084
7085     *length += 4096;
7086     buffer = (guint8 *) g_realloc (buffer, *length);
7087     z.next_out = (Bytef *) (buffer + z.total_out);
7088     z.avail_out += 4096;
7089   } while (z.avail_in > 0);
7090
7091   if (ret != Z_STREAM_END) {
7092     g_free (buffer);
7093     buffer = NULL;
7094     *length = 0;
7095   } else {
7096     *length = z.total_out;
7097   }
7098
7099   inflateEnd (&z);
7100
7101   return buffer;
7102 }
7103 #endif /* HAVE_ZLIB */
7104
7105 static gboolean
7106 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7107 {
7108   GNode *cmov;
7109
7110   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7111
7112   /* counts as header data */
7113   qtdemux->header_size += length;
7114
7115   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7116   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7117
7118   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7119   if (cmov) {
7120     guint32 method;
7121     GNode *dcom;
7122     GNode *cmvd;
7123     guint32 dcom_len;
7124
7125     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7126     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7127     if (dcom == NULL || cmvd == NULL)
7128       goto invalid_compression;
7129
7130     dcom_len = QT_UINT32 (dcom->data);
7131     if (dcom_len < 12)
7132       goto invalid_compression;
7133
7134     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7135     switch (method) {
7136 #ifdef HAVE_ZLIB
7137       case FOURCC_zlib:{
7138         guint uncompressed_length;
7139         guint compressed_length;
7140         guint8 *buf;
7141         guint32 cmvd_len;
7142
7143         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7144         if (cmvd_len < 12)
7145           goto invalid_compression;
7146
7147         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7148         compressed_length = cmvd_len - 12;
7149         GST_LOG ("length = %u", uncompressed_length);
7150
7151         buf =
7152             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7153             compressed_length, &uncompressed_length);
7154
7155         if (buf) {
7156           qtdemux->moov_node_compressed = qtdemux->moov_node;
7157           qtdemux->moov_node = g_node_new (buf);
7158
7159           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7160               uncompressed_length);
7161         }
7162         break;
7163       }
7164 #endif /* HAVE_ZLIB */
7165       default:
7166         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7167             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7168         break;
7169     }
7170   }
7171   return TRUE;
7172
7173   /* ERRORS */
7174 invalid_compression:
7175   {
7176     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7177     return FALSE;
7178   }
7179 }
7180
7181 static gboolean
7182 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7183     const guint8 * end)
7184 {
7185   while (G_UNLIKELY (buf < end)) {
7186     GNode *child;
7187     guint32 len;
7188
7189     if (G_UNLIKELY (buf + 4 > end)) {
7190       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7191       break;
7192     }
7193     len = QT_UINT32 (buf);
7194     if (G_UNLIKELY (len == 0)) {
7195       GST_LOG_OBJECT (qtdemux, "empty container");
7196       break;
7197     }
7198     if (G_UNLIKELY (len < 8)) {
7199       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7200       break;
7201     }
7202     if (G_UNLIKELY (len > (end - buf))) {
7203       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7204           (gint) (end - buf));
7205       break;
7206     }
7207
7208     child = g_node_new ((guint8 *) buf);
7209     g_node_append (node, child);
7210     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7211     qtdemux_parse_node (qtdemux, child, buf, len);
7212
7213     buf += len;
7214   }
7215   return TRUE;
7216 }
7217
7218 static gboolean
7219 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7220     GNode * xdxt)
7221 {
7222   int len = QT_UINT32 (xdxt->data);
7223   guint8 *buf = xdxt->data;
7224   guint8 *end = buf + len;
7225   GstBuffer *buffer;
7226
7227   /* skip size and type */
7228   buf += 8;
7229   end -= 8;
7230
7231   while (buf < end) {
7232     gint size;
7233     guint32 type;
7234
7235     size = QT_UINT32 (buf);
7236     type = QT_FOURCC (buf + 4);
7237
7238     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7239
7240     if (buf + size > end || size <= 0)
7241       break;
7242
7243     buf += 8;
7244     size -= 8;
7245
7246     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7247         GST_FOURCC_ARGS (type));
7248
7249     switch (type) {
7250       case FOURCC_tCtH:
7251         buffer = gst_buffer_new_and_alloc (size);
7252         gst_buffer_fill (buffer, 0, buf, size);
7253         stream->buffers = g_slist_append (stream->buffers, buffer);
7254         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7255         break;
7256       case FOURCC_tCt_:
7257         buffer = gst_buffer_new_and_alloc (size);
7258         gst_buffer_fill (buffer, 0, buf, size);
7259         stream->buffers = g_slist_append (stream->buffers, buffer);
7260         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7261         break;
7262       case FOURCC_tCtC:
7263         buffer = gst_buffer_new_and_alloc (size);
7264         gst_buffer_fill (buffer, 0, buf, size);
7265         stream->buffers = g_slist_append (stream->buffers, buffer);
7266         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7267         break;
7268       default:
7269         GST_WARNING_OBJECT (qtdemux,
7270             "unknown theora cookie %" GST_FOURCC_FORMAT,
7271             GST_FOURCC_ARGS (type));
7272         break;
7273     }
7274     buf += size;
7275   }
7276   return TRUE;
7277 }
7278
7279 static gboolean
7280 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7281     guint length)
7282 {
7283   guint32 fourcc = 0;
7284   guint32 node_length = 0;
7285   const QtNodeType *type;
7286   const guint8 *end;
7287
7288   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7289
7290   if (G_UNLIKELY (length < 8))
7291     goto not_enough_data;
7292
7293   node_length = QT_UINT32 (buffer);
7294   fourcc = QT_FOURCC (buffer + 4);
7295
7296   /* ignore empty nodes */
7297   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7298     return TRUE;
7299
7300   type = qtdemux_type_get (fourcc);
7301
7302   end = buffer + length;
7303
7304   GST_LOG_OBJECT (qtdemux,
7305       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7306       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7307
7308   if (node_length > length)
7309     goto broken_atom_size;
7310
7311   if (type->flags & QT_FLAG_CONTAINER) {
7312     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7313   } else {
7314     switch (fourcc) {
7315       case FOURCC_stsd:
7316       {
7317         if (node_length < 20) {
7318           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7319           break;
7320         }
7321         GST_DEBUG_OBJECT (qtdemux,
7322             "parsing stsd (sample table, sample description) atom");
7323         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7324         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7325         break;
7326       }
7327       case FOURCC_mp4a:
7328       case FOURCC_alac:
7329       case FOURCC_fLaC:
7330       {
7331         guint32 version;
7332         guint32 offset;
7333         guint min_size;
7334
7335         /* also read alac (or whatever) in stead of mp4a in the following,
7336          * since a similar layout is used in other cases as well */
7337         if (fourcc == FOURCC_mp4a)
7338           min_size = 20;
7339         else if (fourcc == FOURCC_fLaC)
7340           min_size = 86;
7341         else
7342           min_size = 40;
7343
7344         /* There are two things we might encounter here: a true mp4a atom, and
7345            an mp4a entry in an stsd atom. The latter is what we're interested
7346            in, and it looks like an atom, but isn't really one. The true mp4a
7347            atom is short, so we detect it based on length here. */
7348         if (length < min_size) {
7349           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7350               GST_FOURCC_ARGS (fourcc));
7351           break;
7352         }
7353
7354         /* 'version' here is the sound sample description version. Types 0 and
7355            1 are documented in the QTFF reference, but type 2 is not: it's
7356            described in Apple header files instead (struct SoundDescriptionV2
7357            in Movies.h) */
7358         version = QT_UINT16 (buffer + 16);
7359
7360         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7361             GST_FOURCC_ARGS (fourcc), version);
7362
7363         /* parse any esds descriptors */
7364         switch (version) {
7365           case 0:
7366             offset = 0x24;
7367             break;
7368           case 1:
7369             offset = 0x34;
7370             break;
7371           case 2:
7372             offset = 0x48;
7373             break;
7374           default:
7375             GST_WARNING_OBJECT (qtdemux,
7376                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7377                 GST_FOURCC_ARGS (fourcc), version);
7378             offset = 0;
7379             break;
7380         }
7381         if (offset)
7382           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7383         break;
7384       }
7385       case FOURCC_mp4v:
7386       case FOURCC_MP4V:
7387       case FOURCC_fmp4:
7388       case FOURCC_FMP4:
7389       case FOURCC_apcs:
7390       case FOURCC_apch:
7391       case FOURCC_apcn:
7392       case FOURCC_apco:
7393       case FOURCC_ap4h:
7394       case FOURCC_xvid:
7395       case FOURCC_XVID:
7396       case FOURCC_H264:
7397       case FOURCC_avc1:
7398       case FOURCC_avc3:
7399       case FOURCC_H265:
7400       case FOURCC_hvc1:
7401       case FOURCC_hev1:
7402       case FOURCC_mjp2:
7403       case FOURCC_encv:
7404       {
7405         guint32 version;
7406         guint32 str_len;
7407
7408         /* codec_data is contained inside these atoms, which all have
7409          * the same format. */
7410         /* video sample description size is 86 bytes without extension.
7411          * node_length have to be bigger than 86 bytes because video sample
7412          * description can include extenstions such as esds, fiel, glbl, etc. */
7413         if (node_length < 86) {
7414           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7415               " sample description length too short (%u < 86)",
7416               GST_FOURCC_ARGS (fourcc), node_length);
7417           break;
7418         }
7419
7420         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7421             GST_FOURCC_ARGS (fourcc));
7422
7423         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7424          *              its data format.
7425          * revision level (2 bytes) : must be set to 0. */
7426         version = QT_UINT32 (buffer + 16);
7427         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7428
7429         /* compressor name : PASCAL string and informative purposes
7430          * first byte : the number of bytes to be displayed.
7431          *              it has to be less than 32 because it is reserved
7432          *              space of 32 bytes total including itself. */
7433         str_len = QT_UINT8 (buffer + 50);
7434         if (str_len < 32)
7435           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7436               (char *) buffer + 51);
7437         else
7438           GST_WARNING_OBJECT (qtdemux,
7439               "compressorname length too big (%u > 31)", str_len);
7440
7441         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7442             end - buffer);
7443         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7444         break;
7445       }
7446       case FOURCC_meta:
7447       {
7448         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7449         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7450         break;
7451       }
7452       case FOURCC_mp4s:
7453       {
7454         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7455         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7456         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7457         break;
7458       }
7459       case FOURCC_XiTh:
7460       {
7461         guint32 version;
7462         guint32 offset;
7463
7464         if (length < 16) {
7465           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7466               GST_FOURCC_ARGS (fourcc));
7467           break;
7468         }
7469
7470         version = QT_UINT32 (buffer + 12);
7471         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7472
7473         switch (version) {
7474           case 0x00000001:
7475             offset = 0x62;
7476             break;
7477           default:
7478             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7479             offset = 0;
7480             break;
7481         }
7482         if (offset) {
7483           if (length < offset) {
7484             GST_WARNING_OBJECT (qtdemux,
7485                 "skipping too small %" GST_FOURCC_FORMAT " box",
7486                 GST_FOURCC_ARGS (fourcc));
7487             break;
7488           }
7489           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7490         }
7491         break;
7492       }
7493       case FOURCC_in24:
7494       {
7495         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7496         break;
7497       }
7498       case FOURCC_uuid:
7499       {
7500         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7501         break;
7502       }
7503       case FOURCC_enca:
7504       {
7505         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7506         break;
7507       }
7508       default:
7509         if (!strcmp (type->name, "unknown"))
7510           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7511         break;
7512     }
7513   }
7514   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7515       GST_FOURCC_ARGS (fourcc));
7516   return TRUE;
7517
7518 /* ERRORS */
7519 not_enough_data:
7520   {
7521     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7522         (_("This file is corrupt and cannot be played.")),
7523         ("Not enough data for an atom header, got only %u bytes", length));
7524     return FALSE;
7525   }
7526 broken_atom_size:
7527   {
7528     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7529         (_("This file is corrupt and cannot be played.")),
7530         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7531             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7532             length));
7533     return FALSE;
7534   }
7535 }
7536
7537 static GNode *
7538 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7539 {
7540   GNode *child;
7541   guint8 *buffer;
7542   guint32 child_fourcc;
7543
7544   for (child = g_node_first_child (node); child;
7545       child = g_node_next_sibling (child)) {
7546     buffer = (guint8 *) child->data;
7547
7548     child_fourcc = QT_FOURCC (buffer + 4);
7549
7550     if (G_UNLIKELY (child_fourcc == fourcc)) {
7551       return child;
7552     }
7553   }
7554   return NULL;
7555 }
7556
7557 static GNode *
7558 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7559     GstByteReader * parser)
7560 {
7561   GNode *child;
7562   guint8 *buffer;
7563   guint32 child_fourcc, child_len;
7564
7565   for (child = g_node_first_child (node); child;
7566       child = g_node_next_sibling (child)) {
7567     buffer = (guint8 *) child->data;
7568
7569     child_len = QT_UINT32 (buffer);
7570     child_fourcc = QT_FOURCC (buffer + 4);
7571
7572     if (G_UNLIKELY (child_fourcc == fourcc)) {
7573       if (G_UNLIKELY (child_len < (4 + 4)))
7574         return NULL;
7575       /* FIXME: must verify if atom length < parent atom length */
7576       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7577       return child;
7578     }
7579   }
7580   return NULL;
7581 }
7582
7583 static GNode *
7584 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7585 {
7586   return g_node_nth_child (node, index);
7587 }
7588
7589 static GNode *
7590 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7591     GstByteReader * parser)
7592 {
7593   GNode *child;
7594   guint8 *buffer;
7595   guint32 child_fourcc, child_len;
7596
7597   for (child = g_node_next_sibling (node); child;
7598       child = g_node_next_sibling (child)) {
7599     buffer = (guint8 *) child->data;
7600
7601     child_fourcc = QT_FOURCC (buffer + 4);
7602
7603     if (child_fourcc == fourcc) {
7604       if (parser) {
7605         child_len = QT_UINT32 (buffer);
7606         if (G_UNLIKELY (child_len < (4 + 4)))
7607           return NULL;
7608         /* FIXME: must verify if atom length < parent atom length */
7609         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7610       }
7611       return child;
7612     }
7613   }
7614   return NULL;
7615 }
7616
7617 static GNode *
7618 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7619 {
7620   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7621 }
7622
7623 static void
7624 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7625 {
7626 /* FIXME: This can only reliably work if demuxers have a
7627  * separate streaming thread per srcpad. This should be
7628  * done in a demuxer base class, which integrates parts
7629  * of multiqueue
7630  *
7631  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7632  */
7633 #if 0
7634   GstQuery *query;
7635
7636   query = gst_query_new_allocation (stream->caps, FALSE);
7637
7638   if (!gst_pad_peer_query (stream->pad, query)) {
7639     /* not a problem, just debug a little */
7640     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7641   }
7642
7643   if (stream->allocator)
7644     gst_object_unref (stream->allocator);
7645
7646   if (gst_query_get_n_allocation_params (query) > 0) {
7647     /* try the allocator */
7648     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7649         &stream->params);
7650     stream->use_allocator = TRUE;
7651   } else {
7652     stream->allocator = NULL;
7653     gst_allocation_params_init (&stream->params);
7654     stream->use_allocator = FALSE;
7655   }
7656   gst_query_unref (query);
7657 #endif
7658 }
7659
7660 static gboolean
7661 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7662     QtDemuxStream * stream)
7663 {
7664   GstStructure *s;
7665   const gchar *selected_system;
7666
7667   g_return_val_if_fail (qtdemux != NULL, FALSE);
7668   g_return_val_if_fail (stream != NULL, FALSE);
7669   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7670       FALSE);
7671
7672   if (stream->protection_scheme_type != FOURCC_cenc) {
7673     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7674     return FALSE;
7675   }
7676   if (qtdemux->protection_system_ids == NULL) {
7677     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7678         "cenc protection system information has been found");
7679     return FALSE;
7680   }
7681   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7682   selected_system = gst_protection_select_system ((const gchar **)
7683       qtdemux->protection_system_ids->pdata);
7684   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7685       qtdemux->protection_system_ids->len - 1);
7686   if (!selected_system) {
7687     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7688         "suitable decryptor element has been found");
7689     return FALSE;
7690   }
7691
7692   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7693   if (!gst_structure_has_name (s, "application/x-cenc")) {
7694     gst_structure_set (s,
7695         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7696         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7697         NULL);
7698     gst_structure_set_name (s, "application/x-cenc");
7699   }
7700   return TRUE;
7701 }
7702
7703 static gboolean
7704 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7705 {
7706   if (stream->subtype == FOURCC_vide) {
7707     /* fps is calculated base on the duration of the average framerate since
7708      * qt does not have a fixed framerate. */
7709     gboolean fps_available = TRUE;
7710
7711     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7712       /* still frame */
7713       CUR_STREAM (stream)->fps_n = 0;
7714       CUR_STREAM (stream)->fps_d = 1;
7715     } else {
7716       if (stream->duration == 0 || stream->n_samples < 2) {
7717         CUR_STREAM (stream)->fps_n = stream->timescale;
7718         CUR_STREAM (stream)->fps_d = 1;
7719         fps_available = FALSE;
7720       } else {
7721         GstClockTime avg_duration;
7722         guint64 duration;
7723         guint32 n_samples;
7724
7725         /* duration and n_samples can be updated for fragmented format
7726          * so, framerate of fragmented format is calculated using data in a moof */
7727         if (qtdemux->fragmented && stream->n_samples_moof > 0
7728             && stream->duration_moof > 0) {
7729           n_samples = stream->n_samples_moof;
7730           duration = stream->duration_moof;
7731         } else {
7732           n_samples = stream->n_samples;
7733           duration = stream->duration;
7734         }
7735
7736         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7737         /* stream->duration is guint64, timescale, n_samples are guint32 */
7738         avg_duration =
7739             gst_util_uint64_scale_round (duration -
7740             stream->first_duration, GST_SECOND,
7741             (guint64) (stream->timescale) * (n_samples - 1));
7742
7743         GST_LOG_OBJECT (qtdemux,
7744             "Calculating avg sample duration based on stream (or moof) duration %"
7745             G_GUINT64_FORMAT
7746             " minus first sample %u, leaving %d samples gives %"
7747             GST_TIME_FORMAT, duration, stream->first_duration,
7748             n_samples - 1, GST_TIME_ARGS (avg_duration));
7749
7750         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7751             &CUR_STREAM (stream)->fps_d);
7752
7753         GST_DEBUG_OBJECT (qtdemux,
7754             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7755             stream->timescale, CUR_STREAM (stream)->fps_n,
7756             CUR_STREAM (stream)->fps_d);
7757       }
7758     }
7759
7760     if (CUR_STREAM (stream)->caps) {
7761       CUR_STREAM (stream)->caps =
7762           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7763
7764       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7765           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7766           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7767
7768       /* set framerate if calculated framerate is reliable */
7769       if (fps_available) {
7770         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7771             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7772             CUR_STREAM (stream)->fps_d, NULL);
7773       }
7774
7775       /* calculate pixel-aspect-ratio using display width and height */
7776       GST_DEBUG_OBJECT (qtdemux,
7777           "video size %dx%d, target display size %dx%d",
7778           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7779           stream->display_width, stream->display_height);
7780       /* qt file might have pasp atom */
7781       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7782         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7783             CUR_STREAM (stream)->par_h);
7784         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7785             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7786             CUR_STREAM (stream)->par_h, NULL);
7787       } else if (stream->display_width > 0 && stream->display_height > 0
7788           && CUR_STREAM (stream)->width > 0
7789           && CUR_STREAM (stream)->height > 0) {
7790         gint n, d;
7791
7792         /* calculate the pixel aspect ratio using the display and pixel w/h */
7793         n = stream->display_width * CUR_STREAM (stream)->height;
7794         d = stream->display_height * CUR_STREAM (stream)->width;
7795         if (n == d)
7796           n = d = 1;
7797         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7798         CUR_STREAM (stream)->par_w = n;
7799         CUR_STREAM (stream)->par_h = d;
7800         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7801             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7802             CUR_STREAM (stream)->par_h, NULL);
7803       }
7804
7805       if (CUR_STREAM (stream)->interlace_mode > 0) {
7806         if (CUR_STREAM (stream)->interlace_mode == 1) {
7807           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7808               G_TYPE_STRING, "progressive", NULL);
7809         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7810           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7811               G_TYPE_STRING, "interleaved", NULL);
7812           if (CUR_STREAM (stream)->field_order == 9) {
7813             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7814                 G_TYPE_STRING, "top-field-first", NULL);
7815           } else if (CUR_STREAM (stream)->field_order == 14) {
7816             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7817                 G_TYPE_STRING, "bottom-field-first", NULL);
7818           }
7819         }
7820       }
7821
7822       /* Create incomplete colorimetry here if needed */
7823       if (CUR_STREAM (stream)->colorimetry.range ||
7824           CUR_STREAM (stream)->colorimetry.matrix ||
7825           CUR_STREAM (stream)->colorimetry.transfer
7826           || CUR_STREAM (stream)->colorimetry.primaries) {
7827         gchar *colorimetry =
7828             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7829         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7830             G_TYPE_STRING, colorimetry, NULL);
7831         g_free (colorimetry);
7832       }
7833
7834       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7835         guint par_w = 1, par_h = 1;
7836
7837         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7838           par_w = CUR_STREAM (stream)->par_w;
7839           par_h = CUR_STREAM (stream)->par_h;
7840         }
7841
7842         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7843                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7844                 par_h)) {
7845           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7846         }
7847
7848         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7849             "multiview-mode", G_TYPE_STRING,
7850             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7851             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7852             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7853       }
7854     }
7855   }
7856
7857   else if (stream->subtype == FOURCC_soun) {
7858     if (CUR_STREAM (stream)->caps) {
7859       CUR_STREAM (stream)->caps =
7860           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7861       if (CUR_STREAM (stream)->rate > 0)
7862         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7863             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7864       if (CUR_STREAM (stream)->n_channels > 0)
7865         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7866             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7867       if (CUR_STREAM (stream)->n_channels > 2) {
7868         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7869          * correctly; this is just the minimum we can do - assume
7870          * we don't actually have any channel positions. */
7871         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7872             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7873       }
7874     }
7875   }
7876
7877   if (stream->pad) {
7878     GstCaps *prev_caps = NULL;
7879
7880     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7881     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7882     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7883     gst_pad_set_active (stream->pad, TRUE);
7884
7885     gst_pad_use_fixed_caps (stream->pad);
7886
7887     if (stream->protected) {
7888       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7889         GST_ERROR_OBJECT (qtdemux,
7890             "Failed to configure protected stream caps.");
7891         return FALSE;
7892       }
7893     }
7894
7895     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7896         CUR_STREAM (stream)->caps);
7897     if (stream->new_stream) {
7898       gchar *stream_id;
7899       GstEvent *event;
7900       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7901
7902       event =
7903           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7904           0);
7905       if (event) {
7906         gst_event_parse_stream_flags (event, &stream_flags);
7907         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7908           qtdemux->have_group_id = TRUE;
7909         else
7910           qtdemux->have_group_id = FALSE;
7911         gst_event_unref (event);
7912       } else if (!qtdemux->have_group_id) {
7913         qtdemux->have_group_id = TRUE;
7914         qtdemux->group_id = gst_util_group_id_next ();
7915       }
7916
7917       stream->new_stream = FALSE;
7918       stream_id =
7919           gst_pad_create_stream_id_printf (stream->pad,
7920           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7921       event = gst_event_new_stream_start (stream_id);
7922       if (qtdemux->have_group_id)
7923         gst_event_set_group_id (event, qtdemux->group_id);
7924       if (stream->disabled)
7925         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7926       if (CUR_STREAM (stream)->sparse) {
7927         stream_flags |= GST_STREAM_FLAG_SPARSE;
7928       } else {
7929         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7930       }
7931       gst_event_set_stream_flags (event, stream_flags);
7932       gst_pad_push_event (stream->pad, event);
7933       g_free (stream_id);
7934     }
7935
7936     prev_caps = gst_pad_get_current_caps (stream->pad);
7937
7938     if (CUR_STREAM (stream)->caps) {
7939       if (!prev_caps
7940           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
7941         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7942             CUR_STREAM (stream)->caps);
7943         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
7944       } else {
7945         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7946       }
7947     } else {
7948       GST_WARNING_OBJECT (qtdemux, "stream without caps");
7949     }
7950
7951     if (prev_caps)
7952       gst_caps_unref (prev_caps);
7953     stream->new_caps = FALSE;
7954   }
7955   return TRUE;
7956 }
7957
7958 static void
7959 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
7960     QtDemuxStream * stream)
7961 {
7962   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
7963     return;
7964
7965   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
7966       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
7967   stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
7968   stream->new_caps = TRUE;
7969 }
7970
7971 static gboolean
7972 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
7973     QtDemuxStream * stream, GstTagList * list)
7974 {
7975   gboolean ret = TRUE;
7976   /* consistent default for push based mode */
7977   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
7978
7979   if (stream->subtype == FOURCC_vide) {
7980     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
7981
7982     stream->pad =
7983         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
7984     g_free (name);
7985
7986     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
7987       gst_object_unref (stream->pad);
7988       stream->pad = NULL;
7989       ret = FALSE;
7990       goto done;
7991     }
7992
7993     qtdemux->n_video_streams++;
7994   } else if (stream->subtype == FOURCC_soun) {
7995     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
7996
7997     stream->pad =
7998         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
7999     g_free (name);
8000     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8001       gst_object_unref (stream->pad);
8002       stream->pad = NULL;
8003       ret = FALSE;
8004       goto done;
8005     }
8006     qtdemux->n_audio_streams++;
8007   } else if (stream->subtype == FOURCC_strm) {
8008     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8009   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8010       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8011     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8012
8013     stream->pad =
8014         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8015     g_free (name);
8016     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8017       gst_object_unref (stream->pad);
8018       stream->pad = NULL;
8019       ret = FALSE;
8020       goto done;
8021     }
8022     qtdemux->n_sub_streams++;
8023   } else if (CUR_STREAM (stream)->caps) {
8024     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8025
8026     stream->pad =
8027         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8028     g_free (name);
8029     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8030       gst_object_unref (stream->pad);
8031       stream->pad = NULL;
8032       ret = FALSE;
8033       goto done;
8034     }
8035     qtdemux->n_video_streams++;
8036   } else {
8037     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8038     goto done;
8039   }
8040
8041   if (stream->pad) {
8042     GList *l;
8043
8044     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8045         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8046     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8047     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8048
8049     if (stream->stream_tags)
8050       gst_tag_list_unref (stream->stream_tags);
8051     stream->stream_tags = list;
8052     list = NULL;
8053     /* global tags go on each pad anyway */
8054     stream->send_global_tags = TRUE;
8055     /* send upstream GST_EVENT_PROTECTION events that were received before
8056        this source pad was created */
8057     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8058       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8059   }
8060 done:
8061   if (list)
8062     gst_tag_list_unref (list);
8063   return ret;
8064 }
8065
8066 /* find next atom with @fourcc starting at @offset */
8067 static GstFlowReturn
8068 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8069     guint64 * length, guint32 fourcc)
8070 {
8071   GstFlowReturn ret;
8072   guint32 lfourcc;
8073   GstBuffer *buf;
8074
8075   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8076       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8077
8078   while (TRUE) {
8079     GstMapInfo map;
8080
8081     buf = NULL;
8082     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8083     if (G_UNLIKELY (ret != GST_FLOW_OK))
8084       goto locate_failed;
8085     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8086       /* likely EOF */
8087       ret = GST_FLOW_EOS;
8088       gst_buffer_unref (buf);
8089       goto locate_failed;
8090     }
8091     gst_buffer_map (buf, &map, GST_MAP_READ);
8092     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8093     gst_buffer_unmap (buf, &map);
8094     gst_buffer_unref (buf);
8095
8096     if (G_UNLIKELY (*length == 0)) {
8097       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8098       ret = GST_FLOW_ERROR;
8099       goto locate_failed;
8100     }
8101
8102     if (lfourcc == fourcc) {
8103       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8104           *offset);
8105       break;
8106     } else {
8107       GST_LOG_OBJECT (qtdemux,
8108           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8109           GST_FOURCC_ARGS (fourcc), *offset);
8110       *offset += *length;
8111     }
8112   }
8113
8114   return GST_FLOW_OK;
8115
8116 locate_failed:
8117   {
8118     /* might simply have had last one */
8119     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8120     return ret;
8121   }
8122 }
8123
8124 /* should only do something in pull mode */
8125 /* call with OBJECT lock */
8126 static GstFlowReturn
8127 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8128 {
8129   guint64 length, offset;
8130   GstBuffer *buf = NULL;
8131   GstFlowReturn ret = GST_FLOW_OK;
8132   GstFlowReturn res = GST_FLOW_OK;
8133   GstMapInfo map;
8134
8135   offset = qtdemux->moof_offset;
8136   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8137
8138   if (!offset) {
8139     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8140     return GST_FLOW_EOS;
8141   }
8142
8143   /* best not do pull etc with lock held */
8144   GST_OBJECT_UNLOCK (qtdemux);
8145
8146   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8147   if (ret != GST_FLOW_OK)
8148     goto flow_failed;
8149
8150   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8151   if (G_UNLIKELY (ret != GST_FLOW_OK))
8152     goto flow_failed;
8153   gst_buffer_map (buf, &map, GST_MAP_READ);
8154   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8155     gst_buffer_unmap (buf, &map);
8156     gst_buffer_unref (buf);
8157     buf = NULL;
8158     goto parse_failed;
8159   }
8160
8161   gst_buffer_unmap (buf, &map);
8162   gst_buffer_unref (buf);
8163   buf = NULL;
8164
8165   offset += length;
8166   /* look for next moof */
8167   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8168   if (G_UNLIKELY (ret != GST_FLOW_OK))
8169     goto flow_failed;
8170
8171 exit:
8172   GST_OBJECT_LOCK (qtdemux);
8173
8174   qtdemux->moof_offset = offset;
8175
8176   return res;
8177
8178 parse_failed:
8179   {
8180     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8181     offset = 0;
8182     res = GST_FLOW_ERROR;
8183     goto exit;
8184   }
8185 flow_failed:
8186   {
8187     /* maybe upstream temporarily flushing */
8188     if (ret != GST_FLOW_FLUSHING) {
8189       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8190       offset = 0;
8191     } else {
8192       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8193       /* resume at current position next time */
8194     }
8195     res = ret;
8196     goto exit;
8197   }
8198 }
8199
8200 /* initialise bytereaders for stbl sub-atoms */
8201 static gboolean
8202 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8203 {
8204   stream->stbl_index = -1;      /* no samples have yet been parsed */
8205   stream->sample_index = -1;
8206
8207   /* time-to-sample atom */
8208   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8209     goto corrupt_file;
8210
8211   /* copy atom data into a new buffer for later use */
8212   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8213
8214   /* skip version + flags */
8215   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8216       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8217     goto corrupt_file;
8218   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8219
8220   /* make sure there's enough data */
8221   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8222     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8223     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8224         stream->n_sample_times);
8225     if (!stream->n_sample_times)
8226       goto corrupt_file;
8227   }
8228
8229   /* sync sample atom */
8230   stream->stps_present = FALSE;
8231   if ((stream->stss_present =
8232           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8233               &stream->stss) ? TRUE : FALSE) == TRUE) {
8234     /* copy atom data into a new buffer for later use */
8235     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8236
8237     /* skip version + flags */
8238     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8239         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8240       goto corrupt_file;
8241
8242     if (stream->n_sample_syncs) {
8243       /* make sure there's enough data */
8244       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8245         goto corrupt_file;
8246     }
8247
8248     /* partial sync sample atom */
8249     if ((stream->stps_present =
8250             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8251                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8252       /* copy atom data into a new buffer for later use */
8253       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8254
8255       /* skip version + flags */
8256       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8257           !gst_byte_reader_get_uint32_be (&stream->stps,
8258               &stream->n_sample_partial_syncs))
8259         goto corrupt_file;
8260
8261       /* if there are no entries, the stss table contains the real
8262        * sync samples */
8263       if (stream->n_sample_partial_syncs) {
8264         /* make sure there's enough data */
8265         if (!qt_atom_parser_has_chunks (&stream->stps,
8266                 stream->n_sample_partial_syncs, 4))
8267           goto corrupt_file;
8268       }
8269     }
8270   }
8271
8272   /* sample size */
8273   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8274     goto no_samples;
8275
8276   /* copy atom data into a new buffer for later use */
8277   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8278
8279   /* skip version + flags */
8280   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8281       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8282     goto corrupt_file;
8283
8284   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8285     goto corrupt_file;
8286
8287   if (!stream->n_samples)
8288     goto no_samples;
8289
8290   /* sample-to-chunk atom */
8291   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8292     goto corrupt_file;
8293
8294   /* copy atom data into a new buffer for later use */
8295   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8296
8297   /* skip version + flags */
8298   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8299       !gst_byte_reader_get_uint32_be (&stream->stsc,
8300           &stream->n_samples_per_chunk))
8301     goto corrupt_file;
8302
8303   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8304       stream->n_samples_per_chunk);
8305
8306   /* make sure there's enough data */
8307   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8308           12))
8309     goto corrupt_file;
8310
8311
8312   /* chunk offset */
8313   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8314     stream->co_size = sizeof (guint32);
8315   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8316           &stream->stco))
8317     stream->co_size = sizeof (guint64);
8318   else
8319     goto corrupt_file;
8320
8321   /* copy atom data into a new buffer for later use */
8322   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8323
8324   /* skip version + flags */
8325   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8326     goto corrupt_file;
8327
8328   /* chunks_are_samples == TRUE means treat chunks as samples */
8329   stream->chunks_are_samples = stream->sample_size
8330       && !CUR_STREAM (stream)->sampled;
8331   if (stream->chunks_are_samples) {
8332     /* treat chunks as samples */
8333     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8334       goto corrupt_file;
8335   } else {
8336     /* skip number of entries */
8337     if (!gst_byte_reader_skip (&stream->stco, 4))
8338       goto corrupt_file;
8339
8340     /* make sure there are enough data in the stsz atom */
8341     if (!stream->sample_size) {
8342       /* different sizes for each sample */
8343       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8344         goto corrupt_file;
8345     }
8346   }
8347
8348   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8349       stream->n_samples, (guint) sizeof (QtDemuxSample),
8350       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8351
8352   if (stream->n_samples >=
8353       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8354     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8355         "be larger than %uMB (broken file?)", stream->n_samples,
8356         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8357     return FALSE;
8358   }
8359
8360   g_assert (stream->samples == NULL);
8361   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8362   if (!stream->samples) {
8363     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8364         stream->n_samples);
8365     return FALSE;
8366   }
8367
8368   /* composition time-to-sample */
8369   if ((stream->ctts_present =
8370           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8371               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8372     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8373
8374     /* copy atom data into a new buffer for later use */
8375     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8376
8377     /* skip version + flags */
8378     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8379         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8380             &stream->n_composition_times))
8381       goto corrupt_file;
8382
8383     /* make sure there's enough data */
8384     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8385             4 + 4))
8386       goto corrupt_file;
8387
8388     /* This is optional, if missing we iterate the ctts */
8389     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8390       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8391           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8392         g_free ((gpointer) cslg.data);
8393         goto corrupt_file;
8394       }
8395     } else {
8396       gint32 cslg_least = 0;
8397       guint num_entries, pos;
8398       gint i;
8399
8400       pos = gst_byte_reader_get_pos (&stream->ctts);
8401       num_entries = stream->n_composition_times;
8402
8403       stream->cslg_shift = 0;
8404
8405       for (i = 0; i < num_entries; i++) {
8406         gint32 offset;
8407
8408         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8409         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8410
8411         if (offset < cslg_least)
8412           cslg_least = offset;
8413       }
8414
8415       if (cslg_least < 0)
8416         stream->cslg_shift = ABS (cslg_least);
8417       else
8418         stream->cslg_shift = 0;
8419
8420       /* reset the reader so we can generate sample table */
8421       gst_byte_reader_set_pos (&stream->ctts, pos);
8422     }
8423   } else {
8424     /* Ensure the cslg_shift value is consistent so we can use it
8425      * unconditionnally to produce TS and Segment */
8426     stream->cslg_shift = 0;
8427   }
8428
8429   return TRUE;
8430
8431 corrupt_file:
8432   {
8433     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8434         (_("This file is corrupt and cannot be played.")), (NULL));
8435     return FALSE;
8436   }
8437 no_samples:
8438   {
8439     gst_qtdemux_stbl_free (stream);
8440     if (!qtdemux->fragmented) {
8441       /* not quite good */
8442       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8443       return FALSE;
8444     } else {
8445       /* may pick up samples elsewhere */
8446       return TRUE;
8447     }
8448   }
8449 }
8450
8451 /* collect samples from the next sample to be parsed up to sample @n for @stream
8452  * by reading the info from @stbl
8453  *
8454  * This code can be executed from both the streaming thread and the seeking
8455  * thread so it takes the object lock to protect itself
8456  */
8457 static gboolean
8458 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8459 {
8460   gint i, j, k;
8461   QtDemuxSample *samples, *first, *cur, *last;
8462   guint32 n_samples_per_chunk;
8463   guint32 n_samples;
8464
8465   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8466       GST_FOURCC_FORMAT ", pad %s",
8467       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8468       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8469
8470   n_samples = stream->n_samples;
8471
8472   if (n >= n_samples)
8473     goto out_of_samples;
8474
8475   GST_OBJECT_LOCK (qtdemux);
8476   if (n <= stream->stbl_index)
8477     goto already_parsed;
8478
8479   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8480
8481   if (!stream->stsz.data) {
8482     /* so we already parsed and passed all the moov samples;
8483      * onto fragmented ones */
8484     g_assert (qtdemux->fragmented);
8485     goto done;
8486   }
8487
8488   /* pointer to the sample table */
8489   samples = stream->samples;
8490
8491   /* starts from -1, moves to the next sample index to parse */
8492   stream->stbl_index++;
8493
8494   /* keep track of the first and last sample to fill */
8495   first = &samples[stream->stbl_index];
8496   last = &samples[n];
8497
8498   if (!stream->chunks_are_samples) {
8499     /* set the sample sizes */
8500     if (stream->sample_size == 0) {
8501       /* different sizes for each sample */
8502       for (cur = first; cur <= last; cur++) {
8503         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8504         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8505             (guint) (cur - samples), cur->size);
8506       }
8507     } else {
8508       /* samples have the same size */
8509       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8510       for (cur = first; cur <= last; cur++)
8511         cur->size = stream->sample_size;
8512     }
8513   }
8514
8515   n_samples_per_chunk = stream->n_samples_per_chunk;
8516   cur = first;
8517
8518   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8519     guint32 last_chunk;
8520
8521     if (stream->stsc_chunk_index >= stream->last_chunk
8522         || stream->stsc_chunk_index < stream->first_chunk) {
8523       stream->first_chunk =
8524           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8525       stream->samples_per_chunk =
8526           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8527       /* starts from 1 */
8528       stream->stsd_sample_description_id =
8529           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8530
8531       /* chunk numbers are counted from 1 it seems */
8532       if (G_UNLIKELY (stream->first_chunk == 0))
8533         goto corrupt_file;
8534
8535       --stream->first_chunk;
8536
8537       /* the last chunk of each entry is calculated by taking the first chunk
8538        * of the next entry; except if there is no next, where we fake it with
8539        * INT_MAX */
8540       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8541         stream->last_chunk = G_MAXUINT32;
8542       } else {
8543         stream->last_chunk =
8544             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8545         if (G_UNLIKELY (stream->last_chunk == 0))
8546           goto corrupt_file;
8547
8548         --stream->last_chunk;
8549       }
8550
8551       GST_LOG_OBJECT (qtdemux,
8552           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8553           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8554           stream->samples_per_chunk, stream->stsd_sample_description_id);
8555
8556       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8557         goto corrupt_file;
8558
8559       if (stream->last_chunk != G_MAXUINT32) {
8560         if (!qt_atom_parser_peek_sub (&stream->stco,
8561                 stream->first_chunk * stream->co_size,
8562                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8563                 &stream->co_chunk))
8564           goto corrupt_file;
8565
8566       } else {
8567         stream->co_chunk = stream->stco;
8568         if (!gst_byte_reader_skip (&stream->co_chunk,
8569                 stream->first_chunk * stream->co_size))
8570           goto corrupt_file;
8571       }
8572
8573       stream->stsc_chunk_index = stream->first_chunk;
8574     }
8575
8576     last_chunk = stream->last_chunk;
8577
8578     if (stream->chunks_are_samples) {
8579       cur = &samples[stream->stsc_chunk_index];
8580
8581       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8582         if (j > n) {
8583           /* save state */
8584           stream->stsc_chunk_index = j;
8585           goto done;
8586         }
8587
8588         cur->offset =
8589             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8590             stream->co_size);
8591
8592         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8593             "%" G_GUINT64_FORMAT, j, cur->offset);
8594
8595         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8596             CUR_STREAM (stream)->bytes_per_frame > 0) {
8597           cur->size =
8598               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8599               CUR_STREAM (stream)->samples_per_frame *
8600               CUR_STREAM (stream)->bytes_per_frame;
8601         } else {
8602           cur->size = stream->samples_per_chunk;
8603         }
8604
8605         GST_DEBUG_OBJECT (qtdemux,
8606             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8607             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8608                     stream->stco_sample_index)), cur->size);
8609
8610         cur->timestamp = stream->stco_sample_index;
8611         cur->duration = stream->samples_per_chunk;
8612         cur->keyframe = TRUE;
8613         cur++;
8614
8615         stream->stco_sample_index += stream->samples_per_chunk;
8616       }
8617       stream->stsc_chunk_index = j;
8618     } else {
8619       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8620         guint32 samples_per_chunk;
8621         guint64 chunk_offset;
8622
8623         if (!stream->stsc_sample_index
8624             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8625                 &stream->chunk_offset))
8626           goto corrupt_file;
8627
8628         samples_per_chunk = stream->samples_per_chunk;
8629         chunk_offset = stream->chunk_offset;
8630
8631         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8632           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8633               G_GUINT64_FORMAT " and size %d",
8634               (guint) (cur - samples), chunk_offset, cur->size);
8635
8636           cur->offset = chunk_offset;
8637           chunk_offset += cur->size;
8638           cur++;
8639
8640           if (G_UNLIKELY (cur > last)) {
8641             /* save state */
8642             stream->stsc_sample_index = k + 1;
8643             stream->chunk_offset = chunk_offset;
8644             stream->stsc_chunk_index = j;
8645             goto done2;
8646           }
8647         }
8648         stream->stsc_sample_index = 0;
8649       }
8650       stream->stsc_chunk_index = j;
8651     }
8652     stream->stsc_index++;
8653   }
8654
8655   if (stream->chunks_are_samples)
8656     goto ctts;
8657 done2:
8658   {
8659     guint32 n_sample_times;
8660
8661     n_sample_times = stream->n_sample_times;
8662     cur = first;
8663
8664     for (i = stream->stts_index; i < n_sample_times; i++) {
8665       guint32 stts_samples;
8666       gint32 stts_duration;
8667       gint64 stts_time;
8668
8669       if (stream->stts_sample_index >= stream->stts_samples
8670           || !stream->stts_sample_index) {
8671
8672         stream->stts_samples =
8673             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8674         stream->stts_duration =
8675             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8676
8677         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8678             i, stream->stts_samples, stream->stts_duration);
8679
8680         stream->stts_sample_index = 0;
8681       }
8682
8683       stts_samples = stream->stts_samples;
8684       stts_duration = stream->stts_duration;
8685       stts_time = stream->stts_time;
8686
8687       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8688         GST_DEBUG_OBJECT (qtdemux,
8689             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8690             (guint) (cur - samples), j,
8691             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8692
8693         cur->timestamp = stts_time;
8694         cur->duration = stts_duration;
8695
8696         /* avoid 32-bit wrap-around,
8697          * but still mind possible 'negative' duration */
8698         stts_time += (gint64) stts_duration;
8699         cur++;
8700
8701         if (G_UNLIKELY (cur > last)) {
8702           /* save values */
8703           stream->stts_time = stts_time;
8704           stream->stts_sample_index = j + 1;
8705           if (stream->stts_sample_index >= stream->stts_samples)
8706             stream->stts_index++;
8707           goto done3;
8708         }
8709       }
8710       stream->stts_sample_index = 0;
8711       stream->stts_time = stts_time;
8712       stream->stts_index++;
8713     }
8714     /* fill up empty timestamps with the last timestamp, this can happen when
8715      * the last samples do not decode and so we don't have timestamps for them.
8716      * We however look at the last timestamp to estimate the track length so we
8717      * need something in here. */
8718     for (; cur < last; cur++) {
8719       GST_DEBUG_OBJECT (qtdemux,
8720           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8721           (guint) (cur - samples),
8722           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8723       cur->timestamp = stream->stts_time;
8724       cur->duration = -1;
8725     }
8726   }
8727 done3:
8728   {
8729     /* sample sync, can be NULL */
8730     if (stream->stss_present == TRUE) {
8731       guint32 n_sample_syncs;
8732
8733       n_sample_syncs = stream->n_sample_syncs;
8734
8735       if (!n_sample_syncs) {
8736         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8737         stream->all_keyframe = TRUE;
8738       } else {
8739         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8740           /* note that the first sample is index 1, not 0 */
8741           guint32 index;
8742
8743           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8744
8745           if (G_LIKELY (index > 0 && index <= n_samples)) {
8746             index -= 1;
8747             samples[index].keyframe = TRUE;
8748             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8749             /* and exit if we have enough samples */
8750             if (G_UNLIKELY (index >= n)) {
8751               i++;
8752               break;
8753             }
8754           }
8755         }
8756         /* save state */
8757         stream->stss_index = i;
8758       }
8759
8760       /* stps marks partial sync frames like open GOP I-Frames */
8761       if (stream->stps_present == TRUE) {
8762         guint32 n_sample_partial_syncs;
8763
8764         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8765
8766         /* if there are no entries, the stss table contains the real
8767          * sync samples */
8768         if (n_sample_partial_syncs) {
8769           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8770             /* note that the first sample is index 1, not 0 */
8771             guint32 index;
8772
8773             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8774
8775             if (G_LIKELY (index > 0 && index <= n_samples)) {
8776               index -= 1;
8777               samples[index].keyframe = TRUE;
8778               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8779               /* and exit if we have enough samples */
8780               if (G_UNLIKELY (index >= n)) {
8781                 i++;
8782                 break;
8783               }
8784             }
8785           }
8786           /* save state */
8787           stream->stps_index = i;
8788         }
8789       }
8790     } else {
8791       /* no stss, all samples are keyframes */
8792       stream->all_keyframe = TRUE;
8793       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8794     }
8795   }
8796
8797 ctts:
8798   /* composition time to sample */
8799   if (stream->ctts_present == TRUE) {
8800     guint32 n_composition_times;
8801     guint32 ctts_count;
8802     gint32 ctts_soffset;
8803
8804     /* Fill in the pts_offsets */
8805     cur = first;
8806     n_composition_times = stream->n_composition_times;
8807
8808     for (i = stream->ctts_index; i < n_composition_times; i++) {
8809       if (stream->ctts_sample_index >= stream->ctts_count
8810           || !stream->ctts_sample_index) {
8811         stream->ctts_count =
8812             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8813         stream->ctts_soffset =
8814             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8815         stream->ctts_sample_index = 0;
8816       }
8817
8818       ctts_count = stream->ctts_count;
8819       ctts_soffset = stream->ctts_soffset;
8820
8821       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8822         cur->pts_offset = ctts_soffset;
8823         cur++;
8824
8825         if (G_UNLIKELY (cur > last)) {
8826           /* save state */
8827           stream->ctts_sample_index = j + 1;
8828           goto done;
8829         }
8830       }
8831       stream->ctts_sample_index = 0;
8832       stream->ctts_index++;
8833     }
8834   }
8835 done:
8836   stream->stbl_index = n;
8837   /* if index has been completely parsed, free data that is no-longer needed */
8838   if (n + 1 == stream->n_samples) {
8839     gst_qtdemux_stbl_free (stream);
8840     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8841     if (qtdemux->pullbased) {
8842       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8843       while (n + 1 == stream->n_samples)
8844         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8845           break;
8846     }
8847   }
8848   GST_OBJECT_UNLOCK (qtdemux);
8849
8850   return TRUE;
8851
8852   /* SUCCESS */
8853 already_parsed:
8854   {
8855     GST_LOG_OBJECT (qtdemux,
8856         "Tried to parse up to sample %u but this sample has already been parsed",
8857         n);
8858     /* if fragmented, there may be more */
8859     if (qtdemux->fragmented && n == stream->stbl_index)
8860       goto done;
8861     GST_OBJECT_UNLOCK (qtdemux);
8862     return TRUE;
8863   }
8864   /* ERRORS */
8865 out_of_samples:
8866   {
8867     GST_LOG_OBJECT (qtdemux,
8868         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8869         stream->n_samples);
8870     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8871         (_("This file is corrupt and cannot be played.")), (NULL));
8872     return FALSE;
8873   }
8874 corrupt_file:
8875   {
8876     GST_OBJECT_UNLOCK (qtdemux);
8877     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8878         (_("This file is corrupt and cannot be played.")), (NULL));
8879     return FALSE;
8880   }
8881 }
8882
8883 /* collect all segment info for @stream.
8884  */
8885 static gboolean
8886 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8887     GNode * trak)
8888 {
8889   GNode *edts;
8890   /* accept edts if they contain gaps at start and there is only
8891    * one media segment */
8892   gboolean allow_pushbased_edts = TRUE;
8893   gint media_segments_count = 0;
8894
8895   /* parse and prepare segment info from the edit list */
8896   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8897   stream->n_segments = 0;
8898   stream->segments = NULL;
8899   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8900     GNode *elst;
8901     gint n_segments;
8902     gint i, count, entry_size;
8903     guint64 time;
8904     GstClockTime stime;
8905     const guint8 *buffer;
8906     guint8 version;
8907     guint32 size;
8908
8909     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8910     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8911       goto done;
8912
8913     buffer = elst->data;
8914
8915     size = QT_UINT32 (buffer);
8916     /* version, flags, n_segments */
8917     if (size < 16) {
8918       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8919       goto done;
8920     }
8921     version = QT_UINT8 (buffer + 8);
8922     entry_size = (version == 1) ? 20 : 12;
8923
8924     n_segments = QT_UINT32 (buffer + 12);
8925
8926     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8927       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8928       goto done;
8929     }
8930
8931     /* we might allocate a bit too much, at least allocate 1 segment */
8932     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8933
8934     /* segments always start from 0 */
8935     time = 0;
8936     stime = 0;
8937     count = 0;
8938     buffer += 16;
8939     for (i = 0; i < n_segments; i++) {
8940       guint64 duration;
8941       guint64 media_time;
8942       gboolean time_valid = TRUE;
8943       QtDemuxSegment *segment;
8944       guint32 rate_int;
8945       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8946
8947       if (version == 1) {
8948         media_time = QT_UINT64 (buffer + 8);
8949         duration = QT_UINT64 (buffer);
8950         if (media_time == G_MAXUINT64)
8951           time_valid = FALSE;
8952       } else {
8953         media_time = QT_UINT32 (buffer + 4);
8954         duration = QT_UINT32 (buffer);
8955         if (media_time == G_MAXUINT32)
8956           time_valid = FALSE;
8957       }
8958
8959       if (time_valid)
8960         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8961
8962       segment = &stream->segments[count++];
8963
8964       /* time and duration expressed in global timescale */
8965       segment->time = stime;
8966       /* add non scaled values so we don't cause roundoff errors */
8967       if (duration || media_start == GST_CLOCK_TIME_NONE) {
8968         time += duration;
8969         stime = QTTIME_TO_GSTTIME (qtdemux, time);
8970         segment->duration = stime - segment->time;
8971       } else {
8972         /* zero duration does not imply media_start == media_stop
8973          * but, only specify media_start.*/
8974         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
8975         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
8976             && stime >= media_start) {
8977           segment->duration = stime - media_start;
8978         } else {
8979           segment->duration = GST_CLOCK_TIME_NONE;
8980         }
8981       }
8982       segment->stop_time = stime;
8983
8984       segment->trak_media_start = media_time;
8985       /* media_time expressed in stream timescale */
8986       if (time_valid) {
8987         segment->media_start = media_start;
8988         segment->media_stop = segment->media_start + segment->duration;
8989         media_segments_count++;
8990       } else {
8991         segment->media_start = GST_CLOCK_TIME_NONE;
8992         segment->media_stop = GST_CLOCK_TIME_NONE;
8993       }
8994       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
8995
8996       if (rate_int <= 1) {
8997         /* 0 is not allowed, some programs write 1 instead of the floating point
8998          * value */
8999         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9000             rate_int);
9001         segment->rate = 1;
9002       } else {
9003         segment->rate = rate_int / 65536.0;
9004       }
9005
9006       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9007           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9008           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9009           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9010           i, GST_TIME_ARGS (segment->time),
9011           GST_TIME_ARGS (segment->duration),
9012           GST_TIME_ARGS (segment->media_start), media_time,
9013           GST_TIME_ARGS (segment->media_stop),
9014           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9015           stream->timescale);
9016       if (segment->stop_time > qtdemux->segment.stop) {
9017         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9018             " extends to %" GST_TIME_FORMAT
9019             " past the end of the file duration %" GST_TIME_FORMAT
9020             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9021             GST_TIME_ARGS (qtdemux->segment.stop));
9022         qtdemux->segment.stop = segment->stop_time;
9023       }
9024
9025       buffer += entry_size;
9026     }
9027     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9028     stream->n_segments = count;
9029     if (media_segments_count != 1)
9030       allow_pushbased_edts = FALSE;
9031   }
9032 done:
9033
9034   /* push based does not handle segments, so act accordingly here,
9035    * and warn if applicable */
9036   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9037     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9038     /* remove and use default one below, we stream like it anyway */
9039     g_free (stream->segments);
9040     stream->segments = NULL;
9041     stream->n_segments = 0;
9042   }
9043
9044   /* no segments, create one to play the complete trak */
9045   if (stream->n_segments == 0) {
9046     GstClockTime stream_duration =
9047         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9048
9049     if (stream->segments == NULL)
9050       stream->segments = g_new (QtDemuxSegment, 1);
9051
9052     /* represent unknown our way */
9053     if (stream_duration == 0)
9054       stream_duration = GST_CLOCK_TIME_NONE;
9055
9056     stream->segments[0].time = 0;
9057     stream->segments[0].stop_time = stream_duration;
9058     stream->segments[0].duration = stream_duration;
9059     stream->segments[0].media_start = 0;
9060     stream->segments[0].media_stop = stream_duration;
9061     stream->segments[0].rate = 1.0;
9062     stream->segments[0].trak_media_start = 0;
9063
9064     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9065         GST_TIME_ARGS (stream_duration));
9066     stream->n_segments = 1;
9067     stream->dummy_segment = TRUE;
9068   }
9069   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9070
9071   return TRUE;
9072 }
9073
9074 /*
9075  * Parses the stsd atom of a svq3 trak looking for
9076  * the SMI and gama atoms.
9077  */
9078 static void
9079 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9080     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9081 {
9082   const guint8 *_gamma = NULL;
9083   GstBuffer *_seqh = NULL;
9084   const guint8 *stsd_data = stsd_entry_data;
9085   guint32 length = QT_UINT32 (stsd_data);
9086   guint16 version;
9087
9088   if (length < 32) {
9089     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9090     goto end;
9091   }
9092
9093   stsd_data += 16;
9094   length -= 16;
9095   version = QT_UINT16 (stsd_data);
9096   if (version == 3) {
9097     if (length >= 70) {
9098       length -= 70;
9099       stsd_data += 70;
9100       while (length > 8) {
9101         guint32 fourcc, size;
9102         const guint8 *data;
9103         size = QT_UINT32 (stsd_data);
9104         fourcc = QT_FOURCC (stsd_data + 4);
9105         data = stsd_data + 8;
9106
9107         if (size == 0) {
9108           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9109               "svq3 atom parsing");
9110           goto end;
9111         }
9112
9113         switch (fourcc) {
9114           case FOURCC_gama:{
9115             if (size == 12) {
9116               _gamma = data;
9117             } else {
9118               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9119                   " for gama atom, expected 12", size);
9120             }
9121             break;
9122           }
9123           case FOURCC_SMI_:{
9124             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9125               guint32 seqh_size;
9126               if (_seqh != NULL) {
9127                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9128                     " found, ignoring");
9129               } else {
9130                 seqh_size = QT_UINT32 (data + 4);
9131                 if (seqh_size > 0) {
9132                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9133                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9134                 }
9135               }
9136             }
9137             break;
9138           }
9139           default:{
9140             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9141                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9142           }
9143         }
9144
9145         if (size <= length) {
9146           length -= size;
9147           stsd_data += size;
9148         }
9149       }
9150     } else {
9151       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9152     }
9153   } else {
9154     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9155         G_GUINT16_FORMAT, version);
9156     goto end;
9157   }
9158
9159 end:
9160   if (gamma) {
9161     *gamma = _gamma;
9162   }
9163   if (seqh) {
9164     *seqh = _seqh;
9165   } else if (_seqh) {
9166     gst_buffer_unref (_seqh);
9167   }
9168 }
9169
9170 static gchar *
9171 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9172 {
9173   GNode *dinf;
9174   GstByteReader dref;
9175   gchar *uri = NULL;
9176
9177   /*
9178    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9179    * atom that might contain a 'data' atom with the rtsp uri.
9180    * This case was reported in bug #597497, some info about
9181    * the hndl atom can be found in TN1195
9182    */
9183   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9184   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9185
9186   if (dinf) {
9187     guint32 dref_num_entries = 0;
9188     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9189         gst_byte_reader_skip (&dref, 4) &&
9190         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9191       gint i;
9192
9193       /* search dref entries for hndl atom */
9194       for (i = 0; i < dref_num_entries; i++) {
9195         guint32 size = 0, type;
9196         guint8 string_len = 0;
9197         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9198             qt_atom_parser_get_fourcc (&dref, &type)) {
9199           if (type == FOURCC_hndl) {
9200             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9201
9202             /* skip data reference handle bytes and the
9203              * following pascal string and some extra 4
9204              * bytes I have no idea what are */
9205             if (!gst_byte_reader_skip (&dref, 4) ||
9206                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9207                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9208               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9209               break;
9210             }
9211
9212             /* iterate over the atoms to find the data atom */
9213             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9214               guint32 atom_size;
9215               guint32 atom_type;
9216
9217               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9218                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9219                 if (atom_type == FOURCC_data) {
9220                   const guint8 *uri_aux = NULL;
9221
9222                   /* found the data atom that might contain the rtsp uri */
9223                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9224                       "hndl atom, interpreting it as an URI");
9225                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9226                           &uri_aux)) {
9227                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9228                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9229                     else
9230                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9231                           "didn't contain a rtsp address");
9232                   } else {
9233                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9234                         "atom contents");
9235                   }
9236                   break;
9237                 }
9238                 /* skipping to the next entry */
9239                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9240                   break;
9241               } else {
9242                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9243                     "atom header");
9244                 break;
9245               }
9246             }
9247             break;
9248           }
9249           /* skip to the next entry */
9250           if (!gst_byte_reader_skip (&dref, size - 8))
9251             break;
9252         } else {
9253           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9254         }
9255       }
9256       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9257     }
9258   }
9259   return uri;
9260 }
9261
9262 #define AMR_NB_ALL_MODES        0x81ff
9263 #define AMR_WB_ALL_MODES        0x83ff
9264 static guint
9265 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9266 {
9267   /* The 'damr' atom is of the form:
9268    *
9269    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9270    *    32 b       8 b          16 b           8 b                 8 b
9271    *
9272    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9273    * represents the highest mode used in the stream (and thus the maximum
9274    * bitrate), with a couple of special cases as seen below.
9275    */
9276
9277   /* Map of frame type ID -> bitrate */
9278   static const guint nb_bitrates[] = {
9279     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9280   };
9281   static const guint wb_bitrates[] = {
9282     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9283   };
9284   GstMapInfo map;
9285   gsize max_mode;
9286   guint16 mode_set;
9287
9288   gst_buffer_map (buf, &map, GST_MAP_READ);
9289
9290   if (map.size != 0x11) {
9291     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9292     goto bad_data;
9293   }
9294
9295   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9296     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9297         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9298     goto bad_data;
9299   }
9300
9301   mode_set = QT_UINT16 (map.data + 13);
9302
9303   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9304     max_mode = 7 + (wb ? 1 : 0);
9305   else
9306     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9307     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9308
9309   if (max_mode == -1) {
9310     GST_DEBUG ("No mode indication was found (mode set) = %x",
9311         (guint) mode_set);
9312     goto bad_data;
9313   }
9314
9315   gst_buffer_unmap (buf, &map);
9316   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9317
9318 bad_data:
9319   gst_buffer_unmap (buf, &map);
9320   return 0;
9321 }
9322
9323 static gboolean
9324 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9325     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9326 {
9327   /*
9328    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9329    * [0 1 2]
9330    * [3 4 5]
9331    * [6 7 8]
9332    */
9333
9334   if (gst_byte_reader_get_remaining (reader) < 36)
9335     return FALSE;
9336
9337   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9338   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9339   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9340   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9341   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9342   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9343   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9344   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9345   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9346
9347   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9348   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9349       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9350       matrix[2] & 0xFF);
9351   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9352       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9353       matrix[5] & 0xFF);
9354   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9355       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9356       matrix[8] & 0xFF);
9357
9358   return TRUE;
9359 }
9360
9361 static void
9362 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9363     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9364 {
9365
9366 /* [a b c]
9367  * [d e f]
9368  * [g h i]
9369  *
9370  * This macro will only compare value abdegh, it expects cfi to have already
9371  * been checked
9372  */
9373 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9374                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9375
9376   /* only handle the cases where the last column has standard values */
9377   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9378     const gchar *rotation_tag = NULL;
9379
9380     /* no rotation needed */
9381     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9382       /* NOP */
9383     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9384       rotation_tag = "rotate-90";
9385     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9386       rotation_tag = "rotate-180";
9387     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9388       rotation_tag = "rotate-270";
9389     } else {
9390       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9391     }
9392
9393     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9394         rotation_tag);
9395     if (rotation_tag != NULL) {
9396       if (*taglist == NULL)
9397         *taglist = gst_tag_list_new_empty ();
9398       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9399           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9400     }
9401   } else {
9402     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9403   }
9404 }
9405
9406 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9407  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9408  * Common Encryption (cenc), the function will also parse the tenc box (defined
9409  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9410  * (typically an enc[v|a|t|s] sample entry); the function will set
9411  * @original_fmt to the fourcc of the original unencrypted stream format.
9412  * Returns TRUE if successful; FALSE otherwise. */
9413 static gboolean
9414 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9415     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9416 {
9417   GNode *sinf;
9418   GNode *frma;
9419   GNode *schm;
9420   GNode *schi;
9421
9422   g_return_val_if_fail (qtdemux != NULL, FALSE);
9423   g_return_val_if_fail (stream != NULL, FALSE);
9424   g_return_val_if_fail (container != NULL, FALSE);
9425   g_return_val_if_fail (original_fmt != NULL, FALSE);
9426
9427   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9428   if (G_UNLIKELY (!sinf)) {
9429     if (stream->protection_scheme_type == FOURCC_cenc) {
9430       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9431           "mandatory for Common Encryption");
9432       return FALSE;
9433     }
9434     return TRUE;
9435   }
9436
9437   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9438   if (G_UNLIKELY (!frma)) {
9439     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9440     return FALSE;
9441   }
9442
9443   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9444   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9445       GST_FOURCC_ARGS (*original_fmt));
9446
9447   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9448   if (!schm) {
9449     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9450     return FALSE;
9451   }
9452   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9453   stream->protection_scheme_version =
9454       QT_UINT32 ((const guint8 *) schm->data + 16);
9455
9456   GST_DEBUG_OBJECT (qtdemux,
9457       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9458       "protection_scheme_version: %#010x",
9459       GST_FOURCC_ARGS (stream->protection_scheme_type),
9460       stream->protection_scheme_version);
9461
9462   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9463   if (!schi) {
9464     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9465     return FALSE;
9466   }
9467   if (stream->protection_scheme_type == FOURCC_cenc) {
9468     QtDemuxCencSampleSetInfo *info;
9469     GNode *tenc;
9470     const guint8 *tenc_data;
9471     guint32 isEncrypted;
9472     guint8 iv_size;
9473     const guint8 *default_kid;
9474     GstBuffer *kid_buf;
9475
9476     if (G_UNLIKELY (!stream->protection_scheme_info))
9477       stream->protection_scheme_info =
9478           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9479
9480     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9481
9482     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9483     if (!tenc) {
9484       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9485           "which is mandatory for Common Encryption");
9486       return FALSE;
9487     }
9488     tenc_data = (const guint8 *) tenc->data + 12;
9489     isEncrypted = QT_UINT24 (tenc_data);
9490     iv_size = QT_UINT8 (tenc_data + 3);
9491     default_kid = (tenc_data + 4);
9492     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9493     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9494     if (info->default_properties)
9495       gst_structure_free (info->default_properties);
9496     info->default_properties =
9497         gst_structure_new ("application/x-cenc",
9498         "iv_size", G_TYPE_UINT, iv_size,
9499         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9500         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9501     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9502         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9503     gst_buffer_unref (kid_buf);
9504   }
9505   return TRUE;
9506 }
9507
9508 /* parse the traks.
9509  * With each track we associate a new QtDemuxStream that contains all the info
9510  * about the trak.
9511  * traks that do not decode to something (like strm traks) will not have a pad.
9512  */
9513 static gboolean
9514 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9515 {
9516   GstByteReader tkhd;
9517   int offset;
9518   GNode *mdia;
9519   GNode *mdhd;
9520   GNode *hdlr;
9521   GNode *minf;
9522   GNode *stbl;
9523   GNode *stsd;
9524   GNode *mp4a;
9525   GNode *mp4v;
9526   GNode *wave;
9527   GNode *esds;
9528   GNode *pasp;
9529   GNode *colr;
9530   GNode *tref;
9531   GNode *udta;
9532   GNode *svmi;
9533   GNode *fiel;
9534
9535   QtDemuxStream *stream = NULL;
9536   gboolean new_stream = FALSE;
9537   gchar *codec = NULL;
9538   const guint8 *stsd_data;
9539   const guint8 *stsd_entry_data;
9540   guint remaining_stsd_len;
9541   guint stsd_entry_count;
9542   guint stsd_index;
9543   guint16 lang_code;            /* quicktime lang code or packed iso code */
9544   guint32 version;
9545   guint32 tkhd_flags = 0;
9546   guint8 tkhd_version = 0;
9547   guint32 w = 0, h = 0;
9548   guint32 fourcc;
9549   guint value_size, stsd_len, len;
9550   guint32 track_id;
9551   guint32 dummy;
9552
9553   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9554
9555   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9556       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9557       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9558     goto corrupt_file;
9559
9560   /* pick between 64 or 32 bits */
9561   value_size = tkhd_version == 1 ? 8 : 4;
9562   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9563       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9564     goto corrupt_file;
9565
9566   if (!qtdemux->got_moov) {
9567     if (qtdemux_find_stream (qtdemux, track_id))
9568       goto existing_stream;
9569     stream = _create_stream ();
9570     stream->track_id = track_id;
9571     new_stream = TRUE;
9572   } else {
9573     stream = qtdemux_find_stream (qtdemux, track_id);
9574     if (!stream) {
9575       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9576       goto skip_track;
9577     }
9578
9579     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9580
9581     /* flush samples data from this track from previous moov */
9582     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9583     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9584   }
9585   /* need defaults for fragments */
9586   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9587
9588   if ((tkhd_flags & 1) == 0)
9589     stream->disabled = TRUE;
9590
9591   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9592       tkhd_version, tkhd_flags, stream->track_id);
9593
9594   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9595     goto corrupt_file;
9596
9597   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9598     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9599     if (qtdemux->major_brand != FOURCC_mjp2 ||
9600         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9601       goto corrupt_file;
9602   }
9603
9604   len = QT_UINT32 ((guint8 *) mdhd->data);
9605   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9606   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9607   if (version == 0x01000000) {
9608     if (len < 38)
9609       goto corrupt_file;
9610     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9611     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9612     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9613   } else {
9614     if (len < 30)
9615       goto corrupt_file;
9616     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9617     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9618     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9619   }
9620
9621   if (lang_code < 0x400) {
9622     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9623   } else if (lang_code == 0x7fff) {
9624     stream->lang_id[0] = 0;     /* unspecified */
9625   } else {
9626     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9627     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9628     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9629     stream->lang_id[3] = 0;
9630   }
9631
9632   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9633       stream->timescale);
9634   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9635       stream->duration);
9636   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9637       lang_code, stream->lang_id);
9638
9639   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9640     goto corrupt_file;
9641
9642   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9643     /* chapters track reference */
9644     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9645     if (chap) {
9646       gsize length = GST_READ_UINT32_BE (chap->data);
9647       if (qtdemux->chapters_track_id)
9648         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9649
9650       if (length >= 12) {
9651         qtdemux->chapters_track_id =
9652             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9653       }
9654     }
9655   }
9656
9657   /* fragmented files may have bogus duration in moov */
9658   if (!qtdemux->fragmented &&
9659       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9660     guint64 tdur1, tdur2;
9661
9662     /* don't overflow */
9663     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9664     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9665
9666     /* HACK:
9667      * some of those trailers, nowadays, have prologue images that are
9668      * themselves video tracks as well. I haven't really found a way to
9669      * identify those yet, except for just looking at their duration. */
9670     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9671       GST_WARNING_OBJECT (qtdemux,
9672           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9673           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9674           "found, assuming preview image or something; skipping track",
9675           stream->duration, stream->timescale, qtdemux->duration,
9676           qtdemux->timescale);
9677       if (new_stream)
9678         gst_qtdemux_stream_free (qtdemux, stream);
9679       return TRUE;
9680     }
9681   }
9682
9683   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9684     goto corrupt_file;
9685
9686   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9687       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9688
9689   len = QT_UINT32 ((guint8 *) hdlr->data);
9690   if (len >= 20)
9691     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9692   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9693       GST_FOURCC_ARGS (stream->subtype));
9694
9695   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9696     goto corrupt_file;
9697
9698   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9699     goto corrupt_file;
9700
9701   /*parse svmi header if existing */
9702   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9703   if (svmi) {
9704     len = QT_UINT32 ((guint8 *) svmi->data);
9705     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9706     if (!version) {
9707       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9708       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9709       guint8 frame_type, frame_layout;
9710
9711       /* MPEG-A stereo video */
9712       if (qtdemux->major_brand == FOURCC_ss02)
9713         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9714
9715       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9716       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9717       switch (frame_type) {
9718         case 0:
9719           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9720           break;
9721         case 1:
9722           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9723           break;
9724         case 2:
9725           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9726           break;
9727         case 3:
9728           /* mode 3 is primary/secondary view sequence, ie
9729            * left/right views in separate tracks. See section 7.2
9730            * of ISO/IEC 23000-11:2009 */
9731           GST_FIXME_OBJECT (qtdemux,
9732               "Implement stereo video in separate streams");
9733       }
9734
9735       if ((frame_layout & 0x1) == 0)
9736         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9737
9738       GST_LOG_OBJECT (qtdemux,
9739           "StereoVideo: composition type: %u, is_left_first: %u",
9740           frame_type, frame_layout);
9741       stream->multiview_mode = mode;
9742       stream->multiview_flags = flags;
9743     }
9744   }
9745
9746   /* parse rest of tkhd */
9747   if (stream->subtype == FOURCC_vide) {
9748     guint32 matrix[9];
9749
9750     /* version 1 uses some 64-bit ints */
9751     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9752       goto corrupt_file;
9753
9754     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9755       goto corrupt_file;
9756
9757     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9758         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9759       goto corrupt_file;
9760
9761     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9762         &stream->stream_tags);
9763   }
9764
9765   /* parse stsd */
9766   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9767     goto corrupt_file;
9768   stsd_data = (const guint8 *) stsd->data;
9769
9770   /* stsd should at least have one entry */
9771   stsd_len = QT_UINT32 (stsd_data);
9772   if (stsd_len < 24) {
9773     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9774     if (stream->subtype == FOURCC_vivo) {
9775       if (new_stream)
9776         gst_qtdemux_stream_free (qtdemux, stream);
9777       return TRUE;
9778     } else {
9779       goto corrupt_file;
9780     }
9781   }
9782
9783   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9784   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9785   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9786   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9787
9788   stsd_entry_data = stsd_data + 16;
9789   remaining_stsd_len = stsd_len - 16;
9790   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9791     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9792
9793     /* and that entry should fit within stsd */
9794     len = QT_UINT32 (stsd_entry_data);
9795     if (len > remaining_stsd_len)
9796       goto corrupt_file;
9797
9798     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9799     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9800         GST_FOURCC_ARGS (entry->fourcc));
9801     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9802
9803     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9804       goto error_encrypted;
9805
9806     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9807       /* FIXME this looks wrong, there might be multiple children
9808        * with the same type */
9809       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9810       stream->protected = TRUE;
9811       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9812         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9813     }
9814
9815     if (stream->subtype == FOURCC_vide) {
9816       gboolean gray;
9817       gint depth, palette_size, palette_count;
9818       guint32 *palette_data = NULL;
9819
9820       entry->sampled = TRUE;
9821
9822       stream->display_width = w >> 16;
9823       stream->display_height = h >> 16;
9824
9825       offset = 16;
9826       if (len < 86)             /* TODO verify */
9827         goto corrupt_file;
9828
9829       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9830       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9831       entry->fps_n = 0;         /* this is filled in later */
9832       entry->fps_d = 0;         /* this is filled in later */
9833       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9834       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9835
9836       /* if color_table_id is 0, ctab atom must follow; however some files
9837        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9838        * if color table is not present we'll correct the value */
9839       if (entry->color_table_id == 0 &&
9840           (len < 90
9841               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9842         entry->color_table_id = -1;
9843       }
9844
9845       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9846           entry->width, entry->height, entry->bits_per_sample,
9847           entry->color_table_id);
9848
9849       depth = entry->bits_per_sample;
9850
9851       /* more than 32 bits means grayscale */
9852       gray = (depth > 32);
9853       /* low 32 bits specify the depth  */
9854       depth &= 0x1F;
9855
9856       /* different number of palette entries is determined by depth. */
9857       palette_count = 0;
9858       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9859         palette_count = (1 << depth);
9860       palette_size = palette_count * 4;
9861
9862       if (entry->color_table_id) {
9863         switch (palette_count) {
9864           case 0:
9865             break;
9866           case 2:
9867             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9868             break;
9869           case 4:
9870             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9871             break;
9872           case 16:
9873             if (gray)
9874               palette_data =
9875                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9876             else
9877               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9878             break;
9879           case 256:
9880             if (gray)
9881               palette_data =
9882                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9883             else
9884               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9885             break;
9886           default:
9887             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9888                 (_("The video in this file might not play correctly.")),
9889                 ("unsupported palette depth %d", depth));
9890             break;
9891         }
9892       } else {
9893         gint i, j, start, end;
9894
9895         if (len < 94)
9896           goto corrupt_file;
9897
9898         /* read table */
9899         start = QT_UINT32 (stsd_entry_data + offset + 70);
9900         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9901         end = QT_UINT16 (stsd_entry_data + offset + 76);
9902
9903         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9904             start, end, palette_count);
9905
9906         if (end > 255)
9907           end = 255;
9908         if (start > end)
9909           start = end;
9910
9911         if (len < 94 + (end - start) * 8)
9912           goto corrupt_file;
9913
9914         /* palette is always the same size */
9915         palette_data = g_malloc0 (256 * 4);
9916         palette_size = 256 * 4;
9917
9918         for (j = 0, i = start; i <= end; j++, i++) {
9919           guint32 a, r, g, b;
9920
9921           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9922           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9923           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9924           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9925
9926           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9927               (g & 0xff00) | (b >> 8);
9928         }
9929       }
9930
9931       if (entry->caps)
9932         gst_caps_unref (entry->caps);
9933
9934       entry->caps =
9935           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
9936           &codec);
9937       if (G_UNLIKELY (!entry->caps)) {
9938         g_free (palette_data);
9939         goto unknown_stream;
9940       }
9941
9942       if (codec) {
9943         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
9944             GST_TAG_VIDEO_CODEC, codec, NULL);
9945         g_free (codec);
9946         codec = NULL;
9947       }
9948
9949       if (palette_data) {
9950         GstStructure *s;
9951
9952         if (entry->rgb8_palette)
9953           gst_memory_unref (entry->rgb8_palette);
9954         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9955             palette_data, palette_size, 0, palette_size, palette_data, g_free);
9956
9957         s = gst_caps_get_structure (entry->caps, 0);
9958
9959         /* non-raw video has a palette_data property. raw video has the palette as
9960          * an extra plane that we append to the output buffers before we push
9961          * them*/
9962         if (!gst_structure_has_name (s, "video/x-raw")) {
9963           GstBuffer *palette;
9964
9965           palette = gst_buffer_new ();
9966           gst_buffer_append_memory (palette, entry->rgb8_palette);
9967           entry->rgb8_palette = NULL;
9968
9969           gst_caps_set_simple (entry->caps, "palette_data",
9970               GST_TYPE_BUFFER, palette, NULL);
9971           gst_buffer_unref (palette);
9972         }
9973       } else if (palette_count != 0) {
9974         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
9975             (NULL), ("Unsupported palette depth %d", depth));
9976       }
9977
9978       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
9979           QT_UINT16 (stsd_entry_data + offset + 32));
9980
9981       esds = NULL;
9982       pasp = NULL;
9983       colr = NULL;
9984       fiel = NULL;
9985       /* pick 'the' stsd child */
9986       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
9987       if (!stream->protected) {
9988         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
9989           mp4v = NULL;
9990         }
9991       } else {
9992         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
9993           mp4v = NULL;
9994         }
9995       }
9996
9997       if (mp4v) {
9998         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
9999         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10000         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10001         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10002       }
10003
10004       if (pasp) {
10005         const guint8 *pasp_data = (const guint8 *) pasp->data;
10006         gint len = QT_UINT32 (pasp_data);
10007
10008         if (len == 16) {
10009           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10010           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10011         } else {
10012           CUR_STREAM (stream)->par_w = 0;
10013           CUR_STREAM (stream)->par_h = 0;
10014         }
10015       } else {
10016         CUR_STREAM (stream)->par_w = 0;
10017         CUR_STREAM (stream)->par_h = 0;
10018       }
10019
10020       if (fiel) {
10021         const guint8 *fiel_data = (const guint8 *) fiel->data;
10022         gint len = QT_UINT32 (fiel_data);
10023
10024         if (len == 10) {
10025           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10026           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10027         }
10028       }
10029
10030       if (colr) {
10031         const guint8 *colr_data = (const guint8 *) colr->data;
10032         gint len = QT_UINT32 (colr_data);
10033
10034         if (len == 19 || len == 18) {
10035           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10036
10037           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10038             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10039             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10040             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10041             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10042
10043             switch (primaries) {
10044               case 1:
10045                 CUR_STREAM (stream)->colorimetry.primaries =
10046                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10047                 break;
10048               case 5:
10049                 CUR_STREAM (stream)->colorimetry.primaries =
10050                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10051                 break;
10052               case 6:
10053                 CUR_STREAM (stream)->colorimetry.primaries =
10054                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10055                 break;
10056               case 9:
10057                 CUR_STREAM (stream)->colorimetry.primaries =
10058                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10059                 break;
10060               default:
10061                 break;
10062             }
10063
10064             switch (transfer_function) {
10065               case 1:
10066                 CUR_STREAM (stream)->colorimetry.transfer =
10067                     GST_VIDEO_TRANSFER_BT709;
10068                 break;
10069               case 7:
10070                 CUR_STREAM (stream)->colorimetry.transfer =
10071                     GST_VIDEO_TRANSFER_SMPTE240M;
10072                 break;
10073               default:
10074                 break;
10075             }
10076
10077             switch (matrix) {
10078               case 1:
10079                 CUR_STREAM (stream)->colorimetry.matrix =
10080                     GST_VIDEO_COLOR_MATRIX_BT709;
10081                 break;
10082               case 6:
10083                 CUR_STREAM (stream)->colorimetry.matrix =
10084                     GST_VIDEO_COLOR_MATRIX_BT601;
10085                 break;
10086               case 7:
10087                 CUR_STREAM (stream)->colorimetry.matrix =
10088                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10089                 break;
10090               case 9:
10091                 CUR_STREAM (stream)->colorimetry.matrix =
10092                     GST_VIDEO_COLOR_MATRIX_BT2020;
10093                 break;
10094               default:
10095                 break;
10096             }
10097
10098             CUR_STREAM (stream)->colorimetry.range =
10099                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10100                 GST_VIDEO_COLOR_RANGE_16_235;
10101           } else {
10102             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10103           }
10104         } else {
10105           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10106         }
10107       }
10108
10109       if (esds) {
10110         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10111             stream->stream_tags);
10112       } else {
10113         switch (fourcc) {
10114           case FOURCC_H264:
10115           case FOURCC_avc1:
10116           case FOURCC_avc3:
10117           {
10118             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10119             const guint8 *avc_data = stsd_entry_data + 0x56;
10120
10121             /* find avcC */
10122             while (len >= 0x8) {
10123               gint size;
10124
10125               if (QT_UINT32 (avc_data) <= len)
10126                 size = QT_UINT32 (avc_data) - 0x8;
10127               else
10128                 size = len - 0x8;
10129
10130               if (size < 1)
10131                 /* No real data, so break out */
10132                 break;
10133
10134               switch (QT_FOURCC (avc_data + 0x4)) {
10135                 case FOURCC_avcC:
10136                 {
10137                   /* parse, if found */
10138                   GstBuffer *buf;
10139
10140                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10141
10142                   /* First 4 bytes are the length of the atom, the next 4 bytes
10143                    * are the fourcc, the next 1 byte is the version, and the
10144                    * subsequent bytes are profile_tier_level structure like data. */
10145                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10146                       avc_data + 8 + 1, size - 1);
10147                   buf = gst_buffer_new_and_alloc (size);
10148                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10149                   gst_caps_set_simple (entry->caps,
10150                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10151                   gst_buffer_unref (buf);
10152
10153                   break;
10154                 }
10155                 case FOURCC_strf:
10156                 {
10157                   GstBuffer *buf;
10158
10159                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10160
10161                   /* First 4 bytes are the length of the atom, the next 4 bytes
10162                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10163                    * next 1 byte is the version, and the
10164                    * subsequent bytes are sequence parameter set like data. */
10165
10166                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10167                   if (size > 1) {
10168                     gst_codec_utils_h264_caps_set_level_and_profile
10169                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10170
10171                     buf = gst_buffer_new_and_alloc (size);
10172                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10173                     gst_caps_set_simple (entry->caps,
10174                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10175                     gst_buffer_unref (buf);
10176                   }
10177                   break;
10178                 }
10179                 case FOURCC_btrt:
10180                 {
10181                   guint avg_bitrate, max_bitrate;
10182
10183                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10184                   if (size < 12)
10185                     break;
10186
10187                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10188                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10189
10190                   if (!max_bitrate && !avg_bitrate)
10191                     break;
10192
10193                   /* Some muxers seem to swap the average and maximum bitrates
10194                    * (I'm looking at you, YouTube), so we swap for sanity. */
10195                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10196                     guint temp = avg_bitrate;
10197
10198                     avg_bitrate = max_bitrate;
10199                     max_bitrate = temp;
10200                   }
10201
10202                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10203                     gst_tag_list_add (stream->stream_tags,
10204                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10205                         max_bitrate, NULL);
10206                   }
10207                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10208                     gst_tag_list_add (stream->stream_tags,
10209                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10210                         NULL);
10211                   }
10212
10213                   break;
10214                 }
10215
10216                 default:
10217                   break;
10218               }
10219
10220               len -= size + 8;
10221               avc_data += size + 8;
10222             }
10223
10224             break;
10225           }
10226           case FOURCC_H265:
10227           case FOURCC_hvc1:
10228           case FOURCC_hev1:
10229           {
10230             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10231             const guint8 *hevc_data = stsd_entry_data + 0x56;
10232
10233             /* find hevc */
10234             while (len >= 0x8) {
10235               gint size;
10236
10237               if (QT_UINT32 (hevc_data) <= len)
10238                 size = QT_UINT32 (hevc_data) - 0x8;
10239               else
10240                 size = len - 0x8;
10241
10242               if (size < 1)
10243                 /* No real data, so break out */
10244                 break;
10245
10246               switch (QT_FOURCC (hevc_data + 0x4)) {
10247                 case FOURCC_hvcC:
10248                 {
10249                   /* parse, if found */
10250                   GstBuffer *buf;
10251
10252                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10253
10254                   /* First 4 bytes are the length of the atom, the next 4 bytes
10255                    * are the fourcc, the next 1 byte is the version, and the
10256                    * subsequent bytes are sequence parameter set like data. */
10257                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10258                       (entry->caps, hevc_data + 8 + 1, size - 1);
10259
10260                   buf = gst_buffer_new_and_alloc (size);
10261                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10262                   gst_caps_set_simple (entry->caps,
10263                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10264                   gst_buffer_unref (buf);
10265                   break;
10266                 }
10267                 default:
10268                   break;
10269               }
10270               len -= size + 8;
10271               hevc_data += size + 8;
10272             }
10273             break;
10274           }
10275           case FOURCC_mp4v:
10276           case FOURCC_MP4V:
10277           case FOURCC_fmp4:
10278           case FOURCC_FMP4:
10279           case FOURCC_xvid:
10280           case FOURCC_XVID:
10281           {
10282             GNode *glbl;
10283
10284             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10285                 GST_FOURCC_ARGS (fourcc));
10286
10287             /* codec data might be in glbl extension atom */
10288             glbl = mp4v ?
10289                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10290             if (glbl) {
10291               guint8 *data;
10292               GstBuffer *buf;
10293               gint len;
10294
10295               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10296               data = glbl->data;
10297               len = QT_UINT32 (data);
10298               if (len > 0x8) {
10299                 len -= 0x8;
10300                 buf = gst_buffer_new_and_alloc (len);
10301                 gst_buffer_fill (buf, 0, data + 8, len);
10302                 gst_caps_set_simple (entry->caps,
10303                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10304                 gst_buffer_unref (buf);
10305               }
10306             }
10307             break;
10308           }
10309           case FOURCC_mjp2:
10310           {
10311             /* see annex I of the jpeg2000 spec */
10312             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10313             const guint8 *data;
10314             const gchar *colorspace = NULL;
10315             gint ncomp = 0;
10316             guint32 ncomp_map = 0;
10317             gint32 *comp_map = NULL;
10318             guint32 nchan_def = 0;
10319             gint32 *chan_def = NULL;
10320
10321             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10322             /* some required atoms */
10323             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10324             if (!mjp2)
10325               break;
10326             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10327             if (!jp2h)
10328               break;
10329
10330             /* number of components; redundant with info in codestream, but useful
10331                to a muxer */
10332             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10333             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10334               break;
10335             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10336
10337             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10338             if (!colr)
10339               break;
10340             GST_DEBUG_OBJECT (qtdemux, "found colr");
10341             /* extract colour space info */
10342             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10343               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10344                 case 16:
10345                   colorspace = "sRGB";
10346                   break;
10347                 case 17:
10348                   colorspace = "GRAY";
10349                   break;
10350                 case 18:
10351                   colorspace = "sYUV";
10352                   break;
10353                 default:
10354                   colorspace = NULL;
10355                   break;
10356               }
10357             }
10358             if (!colorspace)
10359               /* colr is required, and only values 16, 17, and 18 are specified,
10360                  so error if we have no colorspace */
10361               break;
10362
10363             /* extract component mapping */
10364             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10365             if (cmap) {
10366               guint32 cmap_len = 0;
10367               int i;
10368               cmap_len = QT_UINT32 (cmap->data);
10369               if (cmap_len >= 8) {
10370                 /* normal box, subtract off header */
10371                 cmap_len -= 8;
10372                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10373                 if (cmap_len % 4 == 0) {
10374                   ncomp_map = (cmap_len / 4);
10375                   comp_map = g_new0 (gint32, ncomp_map);
10376                   for (i = 0; i < ncomp_map; i++) {
10377                     guint16 cmp;
10378                     guint8 mtyp, pcol;
10379                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10380                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10381                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10382                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10383                   }
10384                 }
10385               }
10386             }
10387             /* extract channel definitions */
10388             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10389             if (cdef) {
10390               guint32 cdef_len = 0;
10391               int i;
10392               cdef_len = QT_UINT32 (cdef->data);
10393               if (cdef_len >= 10) {
10394                 /* normal box, subtract off header and len */
10395                 cdef_len -= 10;
10396                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10397                 if (cdef_len % 6 == 0) {
10398                   nchan_def = (cdef_len / 6);
10399                   chan_def = g_new0 (gint32, nchan_def);
10400                   for (i = 0; i < nchan_def; i++)
10401                     chan_def[i] = -1;
10402                   for (i = 0; i < nchan_def; i++) {
10403                     guint16 cn, typ, asoc;
10404                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10405                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10406                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10407                     if (cn < nchan_def) {
10408                       switch (typ) {
10409                         case 0:
10410                           chan_def[cn] = asoc;
10411                           break;
10412                         case 1:
10413                           chan_def[cn] = 0;     /* alpha */
10414                           break;
10415                         default:
10416                           chan_def[cn] = -typ;
10417                       }
10418                     }
10419                   }
10420                 }
10421               }
10422             }
10423
10424             gst_caps_set_simple (entry->caps,
10425                 "num-components", G_TYPE_INT, ncomp, NULL);
10426             gst_caps_set_simple (entry->caps,
10427                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10428
10429             if (comp_map) {
10430               GValue arr = { 0, };
10431               GValue elt = { 0, };
10432               int i;
10433               g_value_init (&arr, GST_TYPE_ARRAY);
10434               g_value_init (&elt, G_TYPE_INT);
10435               for (i = 0; i < ncomp_map; i++) {
10436                 g_value_set_int (&elt, comp_map[i]);
10437                 gst_value_array_append_value (&arr, &elt);
10438               }
10439               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10440                   "component-map", &arr);
10441               g_value_unset (&elt);
10442               g_value_unset (&arr);
10443               g_free (comp_map);
10444             }
10445
10446             if (chan_def) {
10447               GValue arr = { 0, };
10448               GValue elt = { 0, };
10449               int i;
10450               g_value_init (&arr, GST_TYPE_ARRAY);
10451               g_value_init (&elt, G_TYPE_INT);
10452               for (i = 0; i < nchan_def; i++) {
10453                 g_value_set_int (&elt, chan_def[i]);
10454                 gst_value_array_append_value (&arr, &elt);
10455               }
10456               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10457                   "channel-definitions", &arr);
10458               g_value_unset (&elt);
10459               g_value_unset (&arr);
10460               g_free (chan_def);
10461             }
10462
10463             /* some optional atoms */
10464             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10465             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10466
10467             /* indicate possible fields in caps */
10468             if (field) {
10469               data = (guint8 *) field->data + 8;
10470               if (*data != 1)
10471                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10472                     (gint) * data, NULL);
10473             }
10474             /* add codec_data if provided */
10475             if (prefix) {
10476               GstBuffer *buf;
10477               gint len;
10478
10479               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10480               data = prefix->data;
10481               len = QT_UINT32 (data);
10482               if (len > 0x8) {
10483                 len -= 0x8;
10484                 buf = gst_buffer_new_and_alloc (len);
10485                 gst_buffer_fill (buf, 0, data + 8, len);
10486                 gst_caps_set_simple (entry->caps,
10487                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10488                 gst_buffer_unref (buf);
10489               }
10490             }
10491             break;
10492           }
10493           case FOURCC_SVQ3:
10494           case FOURCC_VP31:
10495           {
10496             GstBuffer *buf;
10497             GstBuffer *seqh = NULL;
10498             const guint8 *gamma_data = NULL;
10499             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10500
10501             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10502                 &seqh);
10503             if (gamma_data) {
10504               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10505                   QT_FP32 (gamma_data), NULL);
10506             }
10507             if (seqh) {
10508               /* sorry for the bad name, but we don't know what this is, other
10509                * than its own fourcc */
10510               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10511                   NULL);
10512               gst_buffer_unref (seqh);
10513             }
10514
10515             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10516             buf = gst_buffer_new_and_alloc (len);
10517             gst_buffer_fill (buf, 0, stsd_data, len);
10518             gst_caps_set_simple (entry->caps,
10519                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10520             gst_buffer_unref (buf);
10521             break;
10522           }
10523           case FOURCC_jpeg:
10524           {
10525             /* https://developer.apple.com/standards/qtff-2001.pdf,
10526              * page 92, "Video Sample Description", under table 3.1 */
10527             GstByteReader br;
10528
10529             const gint compressor_offset =
10530                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10531             const gint min_size = compressor_offset + 32 + 2 + 2;
10532             GNode *jpeg;
10533             guint32 len;
10534             guint16 color_table_id = 0;
10535             gboolean ok;
10536
10537             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10538
10539             /* recover information on interlaced/progressive */
10540             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10541             if (!jpeg)
10542               break;
10543
10544             len = QT_UINT32 (jpeg->data);
10545             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10546                 min_size);
10547             if (len >= min_size) {
10548               gst_byte_reader_init (&br, jpeg->data, len);
10549
10550               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10551               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10552               if (color_table_id != 0) {
10553                 /* the spec says there can be concatenated chunks in the data, and we want
10554                  * to find one called field. Walk through them. */
10555                 gint offset = min_size;
10556                 while (offset + 8 < len) {
10557                   guint32 size = 0, tag;
10558                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10559                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10560                   if (!ok || size < 8) {
10561                     GST_WARNING_OBJECT (qtdemux,
10562                         "Failed to walk optional chunk list");
10563                     break;
10564                   }
10565                   GST_DEBUG_OBJECT (qtdemux,
10566                       "Found optional %4.4s chunk, size %u",
10567                       (const char *) &tag, size);
10568                   if (tag == FOURCC_fiel) {
10569                     guint8 n_fields = 0, ordering = 0;
10570                     gst_byte_reader_get_uint8 (&br, &n_fields);
10571                     gst_byte_reader_get_uint8 (&br, &ordering);
10572                     if (n_fields == 1 || n_fields == 2) {
10573                       GST_DEBUG_OBJECT (qtdemux,
10574                           "Found fiel tag with %u fields, ordering %u",
10575                           n_fields, ordering);
10576                       if (n_fields == 2)
10577                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10578                             "interlace-mode", G_TYPE_STRING, "interleaved",
10579                             NULL);
10580                     } else {
10581                       GST_WARNING_OBJECT (qtdemux,
10582                           "Found fiel tag with invalid fields (%u)", n_fields);
10583                     }
10584                   }
10585                   offset += size;
10586                 }
10587               } else {
10588                 GST_DEBUG_OBJECT (qtdemux,
10589                     "Color table ID is 0, not trying to get interlacedness");
10590               }
10591             } else {
10592               GST_WARNING_OBJECT (qtdemux,
10593                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10594             }
10595
10596             break;
10597           }
10598           case FOURCC_rle_:
10599           case FOURCC_WRLE:
10600           {
10601             gst_caps_set_simple (entry->caps,
10602                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 82),
10603                 NULL);
10604             break;
10605           }
10606           case FOURCC_XiTh:
10607           {
10608             GNode *xith, *xdxt;
10609
10610             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10611             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10612             if (!xith)
10613               break;
10614
10615             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10616             if (!xdxt)
10617               break;
10618
10619             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10620             /* collect the headers and store them in a stream list so that we can
10621              * send them out first */
10622             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10623             break;
10624           }
10625           case FOURCC_ovc1:
10626           {
10627             GNode *ovc1;
10628             guint8 *ovc1_data;
10629             guint ovc1_len;
10630             GstBuffer *buf;
10631
10632             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10633             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10634             if (!ovc1)
10635               break;
10636             ovc1_data = ovc1->data;
10637             ovc1_len = QT_UINT32 (ovc1_data);
10638             if (ovc1_len <= 198) {
10639               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10640               break;
10641             }
10642             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10643             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10644             gst_caps_set_simple (entry->caps,
10645                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10646             gst_buffer_unref (buf);
10647             break;
10648           }
10649           case FOURCC_vc_1:
10650           {
10651             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10652             const guint8 *vc1_data = stsd_entry_data + 0x56;
10653
10654             /* find dvc1 */
10655             while (len >= 8) {
10656               gint size;
10657
10658               if (QT_UINT32 (vc1_data) <= len)
10659                 size = QT_UINT32 (vc1_data) - 8;
10660               else
10661                 size = len - 8;
10662
10663               if (size < 1)
10664                 /* No real data, so break out */
10665                 break;
10666
10667               switch (QT_FOURCC (vc1_data + 0x4)) {
10668                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10669                 {
10670                   GstBuffer *buf;
10671
10672                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10673                   buf = gst_buffer_new_and_alloc (size);
10674                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10675                   gst_caps_set_simple (entry->caps,
10676                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10677                   gst_buffer_unref (buf);
10678                   break;
10679                 }
10680                 default:
10681                   break;
10682               }
10683               len -= size + 8;
10684               vc1_data += size + 8;
10685             }
10686             break;
10687           }
10688           default:
10689             break;
10690         }
10691       }
10692
10693       GST_INFO_OBJECT (qtdemux,
10694           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10695           GST_FOURCC_ARGS (fourcc), entry->caps);
10696
10697     } else if (stream->subtype == FOURCC_soun) {
10698       int version, samplesize;
10699       guint16 compression_id;
10700       gboolean amrwb = FALSE;
10701
10702       offset = 16;
10703       /* sample description entry (16) + sound sample description v0 (20) */
10704       if (len < 36)
10705         goto corrupt_file;
10706
10707       version = QT_UINT32 (stsd_entry_data + offset);
10708       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10709       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10710       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10711       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10712
10713       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10714       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10715           QT_UINT32 (stsd_entry_data + offset + 4));
10716       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10717       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10718       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10719       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10720           QT_UINT16 (stsd_entry_data + offset + 14));
10721       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10722
10723       if (compression_id == 0xfffe)
10724         entry->sampled = TRUE;
10725
10726       /* first assume uncompressed audio */
10727       entry->bytes_per_sample = samplesize / 8;
10728       entry->samples_per_frame = entry->n_channels;
10729       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10730       entry->samples_per_packet = entry->samples_per_frame;
10731       entry->bytes_per_packet = entry->bytes_per_sample;
10732
10733       offset = 36;
10734       switch (fourcc) {
10735           /* Yes, these have to be hard-coded */
10736         case FOURCC_MAC6:
10737         {
10738           entry->samples_per_packet = 6;
10739           entry->bytes_per_packet = 1;
10740           entry->bytes_per_frame = 1 * entry->n_channels;
10741           entry->bytes_per_sample = 1;
10742           entry->samples_per_frame = 6 * entry->n_channels;
10743           break;
10744         }
10745         case FOURCC_MAC3:
10746         {
10747           entry->samples_per_packet = 3;
10748           entry->bytes_per_packet = 1;
10749           entry->bytes_per_frame = 1 * entry->n_channels;
10750           entry->bytes_per_sample = 1;
10751           entry->samples_per_frame = 3 * entry->n_channels;
10752           break;
10753         }
10754         case FOURCC_ima4:
10755         {
10756           entry->samples_per_packet = 64;
10757           entry->bytes_per_packet = 34;
10758           entry->bytes_per_frame = 34 * entry->n_channels;
10759           entry->bytes_per_sample = 2;
10760           entry->samples_per_frame = 64 * entry->n_channels;
10761           break;
10762         }
10763         case FOURCC_ulaw:
10764         case FOURCC_alaw:
10765         {
10766           entry->samples_per_packet = 1;
10767           entry->bytes_per_packet = 1;
10768           entry->bytes_per_frame = 1 * entry->n_channels;
10769           entry->bytes_per_sample = 1;
10770           entry->samples_per_frame = 1 * entry->n_channels;
10771           break;
10772         }
10773         case FOURCC_agsm:
10774         {
10775           entry->samples_per_packet = 160;
10776           entry->bytes_per_packet = 33;
10777           entry->bytes_per_frame = 33 * entry->n_channels;
10778           entry->bytes_per_sample = 2;
10779           entry->samples_per_frame = 160 * entry->n_channels;
10780           break;
10781         }
10782         default:
10783           break;
10784       }
10785
10786       if (version == 0x00010000) {
10787         /* sample description entry (16) + sound sample description v1 (20+16) */
10788         if (len < 52)
10789           goto corrupt_file;
10790
10791         switch (fourcc) {
10792           case FOURCC_twos:
10793           case FOURCC_sowt:
10794           case FOURCC_raw_:
10795             break;
10796           default:
10797           {
10798             /* only parse extra decoding config for non-pcm audio */
10799             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10800             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10801             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10802             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10803
10804             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10805                 entry->samples_per_packet);
10806             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10807                 entry->bytes_per_packet);
10808             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10809                 entry->bytes_per_frame);
10810             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10811                 entry->bytes_per_sample);
10812
10813             if (!entry->sampled && entry->bytes_per_packet) {
10814               entry->samples_per_frame = (entry->bytes_per_frame /
10815                   entry->bytes_per_packet) * entry->samples_per_packet;
10816               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10817                   entry->samples_per_frame);
10818             }
10819             break;
10820           }
10821         }
10822       } else if (version == 0x00020000) {
10823         union
10824         {
10825           gdouble fp;
10826           guint64 val;
10827         } qtfp;
10828
10829         /* sample description entry (16) + sound sample description v2 (56) */
10830         if (len < 72)
10831           goto corrupt_file;
10832
10833         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10834         entry->rate = qtfp.fp;
10835         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10836
10837         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10838         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10839         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10840         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10841             QT_UINT32 (stsd_entry_data + offset + 20));
10842         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10843             QT_UINT32 (stsd_entry_data + offset + 24));
10844         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10845             QT_UINT32 (stsd_entry_data + offset + 28));
10846         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10847             QT_UINT32 (stsd_entry_data + offset + 32));
10848       } else if (version != 0x00000) {
10849         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10850             version);
10851       }
10852
10853       if (entry->caps)
10854         gst_caps_unref (entry->caps);
10855
10856       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10857           stsd_entry_data + 32, len - 16, &codec);
10858
10859       switch (fourcc) {
10860         case FOURCC_in24:
10861         {
10862           GNode *enda;
10863           GNode *in24;
10864
10865           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10866
10867           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10868           if (!enda) {
10869             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10870             if (wave)
10871               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10872           }
10873           if (enda) {
10874             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10875             gst_caps_set_simple (entry->caps,
10876                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10877                 NULL);
10878           }
10879           break;
10880         }
10881         case FOURCC_owma:
10882         {
10883           const guint8 *owma_data;
10884           const gchar *codec_name = NULL;
10885           guint owma_len;
10886           GstBuffer *buf;
10887           gint version = 1;
10888           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10889           /* FIXME this should also be gst_riff_strf_auds,
10890            * but the latter one is actually missing bits-per-sample :( */
10891           typedef struct
10892           {
10893             gint16 wFormatTag;
10894             gint16 nChannels;
10895             gint32 nSamplesPerSec;
10896             gint32 nAvgBytesPerSec;
10897             gint16 nBlockAlign;
10898             gint16 wBitsPerSample;
10899             gint16 cbSize;
10900           } WAVEFORMATEX;
10901           WAVEFORMATEX *wfex;
10902
10903           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10904           owma_data = stsd_entry_data;
10905           owma_len = QT_UINT32 (owma_data);
10906           if (owma_len <= 54) {
10907             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10908             break;
10909           }
10910           wfex = (WAVEFORMATEX *) (owma_data + 36);
10911           buf = gst_buffer_new_and_alloc (owma_len - 54);
10912           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10913           if (wfex->wFormatTag == 0x0161) {
10914             codec_name = "Windows Media Audio";
10915             version = 2;
10916           } else if (wfex->wFormatTag == 0x0162) {
10917             codec_name = "Windows Media Audio 9 Pro";
10918             version = 3;
10919           } else if (wfex->wFormatTag == 0x0163) {
10920             codec_name = "Windows Media Audio 9 Lossless";
10921             /* is that correct? gstffmpegcodecmap.c is missing it, but
10922              * fluendo codec seems to support it */
10923             version = 4;
10924           }
10925
10926           gst_caps_set_simple (entry->caps,
10927               "codec_data", GST_TYPE_BUFFER, buf,
10928               "wmaversion", G_TYPE_INT, version,
10929               "block_align", G_TYPE_INT,
10930               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
10931               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
10932               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
10933               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
10934           gst_buffer_unref (buf);
10935
10936           if (codec_name) {
10937             g_free (codec);
10938             codec = g_strdup (codec_name);
10939           }
10940           break;
10941         }
10942         case FOURCC_wma_:
10943         {
10944           gint len = QT_UINT32 (stsd_entry_data) - offset;
10945           const guint8 *wfex_data = stsd_entry_data + offset;
10946           const gchar *codec_name = NULL;
10947           gint version = 1;
10948           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10949           /* FIXME this should also be gst_riff_strf_auds,
10950            * but the latter one is actually missing bits-per-sample :( */
10951           typedef struct
10952           {
10953             gint16 wFormatTag;
10954             gint16 nChannels;
10955             gint32 nSamplesPerSec;
10956             gint32 nAvgBytesPerSec;
10957             gint16 nBlockAlign;
10958             gint16 wBitsPerSample;
10959             gint16 cbSize;
10960           } WAVEFORMATEX;
10961           WAVEFORMATEX wfex;
10962
10963           /* FIXME: unify with similar wavformatex parsing code above */
10964           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
10965
10966           /* find wfex */
10967           while (len >= 8) {
10968             gint size;
10969
10970             if (QT_UINT32 (wfex_data) <= len)
10971               size = QT_UINT32 (wfex_data) - 8;
10972             else
10973               size = len - 8;
10974
10975             if (size < 1)
10976               /* No real data, so break out */
10977               break;
10978
10979             switch (QT_FOURCC (wfex_data + 4)) {
10980               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
10981               {
10982                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
10983
10984                 if (size < 8 + 18)
10985                   break;
10986
10987                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
10988                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
10989                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
10990                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
10991                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
10992                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
10993                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
10994
10995                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
10996                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
10997                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
10998                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
10999                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11000                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11001
11002                 if (wfex.wFormatTag == 0x0161) {
11003                   codec_name = "Windows Media Audio";
11004                   version = 2;
11005                 } else if (wfex.wFormatTag == 0x0162) {
11006                   codec_name = "Windows Media Audio 9 Pro";
11007                   version = 3;
11008                 } else if (wfex.wFormatTag == 0x0163) {
11009                   codec_name = "Windows Media Audio 9 Lossless";
11010                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11011                    * fluendo codec seems to support it */
11012                   version = 4;
11013                 }
11014
11015                 gst_caps_set_simple (entry->caps,
11016                     "wmaversion", G_TYPE_INT, version,
11017                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11018                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11019                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11020                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11021
11022                 if (size > wfex.cbSize) {
11023                   GstBuffer *buf;
11024
11025                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11026                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11027                       size - wfex.cbSize);
11028                   gst_caps_set_simple (entry->caps,
11029                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11030                   gst_buffer_unref (buf);
11031                 } else {
11032                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11033                 }
11034
11035                 if (codec_name) {
11036                   g_free (codec);
11037                   codec = g_strdup (codec_name);
11038                 }
11039                 break;
11040               }
11041               default:
11042                 break;
11043             }
11044             len -= size + 8;
11045             wfex_data += size + 8;
11046           }
11047           break;
11048         }
11049         case FOURCC_opus:
11050         {
11051           const guint8 *opus_data;
11052           guint8 *channel_mapping = NULL;
11053           guint32 rate;
11054           guint8 channels;
11055           guint8 channel_mapping_family;
11056           guint8 stream_count;
11057           guint8 coupled_count;
11058           guint8 i;
11059
11060           opus_data = stsd_entry_data;
11061
11062           channels = GST_READ_UINT8 (opus_data + 45);
11063           rate = GST_READ_UINT32_LE (opus_data + 48);
11064           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11065           stream_count = GST_READ_UINT8 (opus_data + 55);
11066           coupled_count = GST_READ_UINT8 (opus_data + 56);
11067
11068           if (channels > 0) {
11069             channel_mapping = g_malloc (channels * sizeof (guint8));
11070             for (i = 0; i < channels; i++)
11071               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11072           }
11073
11074           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11075               channel_mapping_family, stream_count, coupled_count,
11076               channel_mapping);
11077           break;
11078         }
11079         default:
11080           break;
11081       }
11082
11083       if (codec) {
11084         GstStructure *s;
11085         gint bitrate = 0;
11086
11087         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11088             GST_TAG_AUDIO_CODEC, codec, NULL);
11089         g_free (codec);
11090         codec = NULL;
11091
11092         /* some bitrate info may have ended up in caps */
11093         s = gst_caps_get_structure (entry->caps, 0);
11094         gst_structure_get_int (s, "bitrate", &bitrate);
11095         if (bitrate > 0)
11096           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11097               GST_TAG_BITRATE, bitrate, NULL);
11098       }
11099
11100       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11101       if (!stream->protected) {
11102       } else {
11103         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11104           mp4v = NULL;
11105         }
11106       }
11107       if (stream->protected && fourcc == FOURCC_mp4a) {
11108         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11109           mp4a = NULL;
11110         }
11111       } else {
11112         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11113           mp4a = NULL;
11114         }
11115       }
11116
11117       wave = NULL;
11118       esds = NULL;
11119       if (mp4a) {
11120         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11121         if (wave)
11122           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11123         if (!esds)
11124           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11125       }
11126
11127
11128       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11129          16 bits is a byte-swapped wave-style codec identifier,
11130          and we can find a WAVE header internally to a 'wave' atom here.
11131          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11132          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11133          is big-endian).
11134        */
11135       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11136         if (len < offset + 20) {
11137           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11138         } else {
11139           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11140           const guint8 *data = stsd_entry_data + offset + 16;
11141           GNode *wavenode;
11142           GNode *waveheadernode;
11143
11144           wavenode = g_node_new ((guint8 *) data);
11145           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11146             const guint8 *waveheader;
11147             guint32 headerlen;
11148
11149             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11150             if (waveheadernode) {
11151               waveheader = (const guint8 *) waveheadernode->data;
11152               headerlen = QT_UINT32 (waveheader);
11153
11154               if (headerlen > 8) {
11155                 gst_riff_strf_auds *header = NULL;
11156                 GstBuffer *headerbuf;
11157                 GstBuffer *extra;
11158
11159                 waveheader += 8;
11160                 headerlen -= 8;
11161
11162                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11163                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11164
11165                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11166                         headerbuf, &header, &extra)) {
11167                   gst_caps_unref (entry->caps);
11168                   /* FIXME: Need to do something with the channel reorder map */
11169                   entry->caps =
11170                       gst_riff_create_audio_caps (header->format, NULL, header,
11171                       extra, NULL, NULL, NULL);
11172
11173                   if (extra)
11174                     gst_buffer_unref (extra);
11175                   g_free (header);
11176                 }
11177               }
11178             } else
11179               GST_DEBUG ("Didn't find waveheadernode for this codec");
11180           }
11181           g_node_destroy (wavenode);
11182         }
11183       } else if (esds) {
11184         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11185             stream->stream_tags);
11186       } else {
11187         switch (fourcc) {
11188 #if 0
11189             /* FIXME: what is in the chunk? */
11190           case FOURCC_QDMC:
11191           {
11192             gint len = QT_UINT32 (stsd_data);
11193
11194             /* seems to be always = 116 = 0x74 */
11195             break;
11196           }
11197 #endif
11198           case FOURCC_QDM2:
11199           {
11200             gint len = QT_UINT32 (stsd_entry_data);
11201
11202             if (len > 0x3C) {
11203               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11204
11205               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11206               gst_caps_set_simple (entry->caps,
11207                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11208               gst_buffer_unref (buf);
11209             }
11210             gst_caps_set_simple (entry->caps,
11211                 "samplesize", G_TYPE_INT, samplesize, NULL);
11212             break;
11213           }
11214           case FOURCC_alac:
11215           {
11216             GNode *alac, *wave = NULL;
11217
11218             /* apparently, m4a has this atom appended directly in the stsd entry,
11219              * while mov has it in a wave atom */
11220             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11221             if (alac) {
11222               /* alac now refers to stsd entry atom */
11223               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11224               if (wave)
11225                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11226               else
11227                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11228             }
11229             if (alac) {
11230               const guint8 *alac_data = alac->data;
11231               gint len = QT_UINT32 (alac->data);
11232               GstBuffer *buf;
11233
11234               if (len < 36) {
11235                 GST_DEBUG_OBJECT (qtdemux,
11236                     "discarding alac atom with unexpected len %d", len);
11237               } else {
11238                 /* codec-data contains alac atom size and prefix,
11239                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11240                 buf = gst_buffer_new_and_alloc (len);
11241                 gst_buffer_fill (buf, 0, alac->data, len);
11242                 gst_caps_set_simple (entry->caps,
11243                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11244                 gst_buffer_unref (buf);
11245
11246                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11247                 entry->n_channels = QT_UINT8 (alac_data + 21);
11248                 entry->rate = QT_UINT32 (alac_data + 32);
11249               }
11250             }
11251             gst_caps_set_simple (entry->caps,
11252                 "samplesize", G_TYPE_INT, samplesize, NULL);
11253             break;
11254           }
11255           case FOURCC_fLaC:
11256           {
11257             /* The codingname of the sample entry is 'fLaC' */
11258             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11259
11260             if (flac) {
11261               /* The 'dfLa' box is added to the sample entry to convey
11262                  initializing information for the decoder. */
11263               const GNode *dfla =
11264                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11265
11266               if (dfla) {
11267                 const guint32 len = QT_UINT32 (dfla->data);
11268
11269                 /* Must contain at least dfLa box header (12),
11270                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11271                 if (len < 50) {
11272                   GST_DEBUG_OBJECT (qtdemux,
11273                       "discarding dfla atom with unexpected len %d", len);
11274                 } else {
11275                   /* skip dfLa header to get the METADATA_BLOCKs */
11276                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11277                   const guint32 metadata_blocks_len = len - 12;
11278
11279                   gchar *stream_marker = g_strdup ("fLaC");
11280                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11281                       strlen (stream_marker));
11282
11283                   guint32 index = 0;
11284                   guint32 remainder = 0;
11285                   guint32 block_size = 0;
11286                   gboolean is_last = FALSE;
11287
11288                   GValue array = G_VALUE_INIT;
11289                   GValue value = G_VALUE_INIT;
11290
11291                   g_value_init (&array, GST_TYPE_ARRAY);
11292                   g_value_init (&value, GST_TYPE_BUFFER);
11293
11294                   gst_value_set_buffer (&value, block);
11295                   gst_value_array_append_value (&array, &value);
11296                   g_value_reset (&value);
11297
11298                   gst_buffer_unref (block);
11299
11300                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11301                    * of data, and we haven't already finished parsing */
11302                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11303                     remainder = metadata_blocks_len - index;
11304
11305                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11306                     block_size = 4 +
11307                         (metadata_blocks[index + 1] << 16) +
11308                         (metadata_blocks[index + 2] << 8) +
11309                         metadata_blocks[index + 3];
11310
11311                     /* be careful not to read off end of box */
11312                     if (block_size > remainder) {
11313                       break;
11314                     }
11315
11316                     is_last = metadata_blocks[index] >> 7;
11317
11318                     block = gst_buffer_new_and_alloc (block_size);
11319
11320                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11321                         block_size);
11322
11323                     gst_value_set_buffer (&value, block);
11324                     gst_value_array_append_value (&array, &value);
11325                     g_value_reset (&value);
11326
11327                     gst_buffer_unref (block);
11328
11329                     index += block_size;
11330                   }
11331
11332                   /* only append the metadata if we successfully read all of it */
11333                   if (is_last) {
11334                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11335                             (stream)->caps, 0), "streamheader", &array);
11336                   } else {
11337                     GST_WARNING_OBJECT (qtdemux,
11338                         "discarding all METADATA_BLOCKs due to invalid "
11339                         "block_size %d at idx %d, rem %d", block_size, index,
11340                         remainder);
11341                   }
11342
11343                   g_value_unset (&value);
11344                   g_value_unset (&array);
11345
11346                   /* The sample rate obtained from the stsd may not be accurate
11347                    * since it cannot represent rates greater than 65535Hz, so
11348                    * override that value with the sample rate from the
11349                    * METADATA_BLOCK_STREAMINFO block */
11350                   CUR_STREAM (stream)->rate =
11351                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11352                 }
11353               }
11354             }
11355             break;
11356           }
11357           case FOURCC_sawb:
11358             /* Fallthrough! */
11359             amrwb = TRUE;
11360           case FOURCC_samr:
11361           {
11362             gint len = QT_UINT32 (stsd_entry_data);
11363
11364             if (len > 0x24) {
11365               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11366               guint bitrate;
11367
11368               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11369
11370               /* If we have enough data, let's try to get the 'damr' atom. See
11371                * the 3GPP container spec (26.244) for more details. */
11372               if ((len - 0x34) > 8 &&
11373                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11374                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11375                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11376               }
11377
11378               gst_caps_set_simple (entry->caps,
11379                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11380               gst_buffer_unref (buf);
11381             }
11382             break;
11383           }
11384           case FOURCC_mp4a:
11385           {
11386             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11387             gint len = QT_UINT32 (stsd_entry_data);
11388
11389             if (len >= 34) {
11390               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11391
11392               if (sound_version == 1) {
11393                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11394                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11395                 guint8 codec_data[2];
11396                 GstBuffer *buf;
11397                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11398
11399                 gint sample_rate_index =
11400                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11401
11402                 /* build AAC codec data */
11403                 codec_data[0] = profile << 3;
11404                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11405                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11406                 codec_data[1] |= (channels & 0xF) << 3;
11407
11408                 buf = gst_buffer_new_and_alloc (2);
11409                 gst_buffer_fill (buf, 0, codec_data, 2);
11410                 gst_caps_set_simple (entry->caps,
11411                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11412                 gst_buffer_unref (buf);
11413               }
11414             }
11415             break;
11416           }
11417           default:
11418             GST_INFO_OBJECT (qtdemux,
11419                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11420             break;
11421         }
11422       }
11423       GST_INFO_OBJECT (qtdemux,
11424           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11425           GST_FOURCC_ARGS (fourcc), entry->caps);
11426
11427     } else if (stream->subtype == FOURCC_strm) {
11428       if (fourcc == FOURCC_rtsp) {
11429         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11430       } else {
11431         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11432             GST_FOURCC_ARGS (fourcc));
11433         goto unknown_stream;
11434       }
11435       entry->sampled = TRUE;
11436     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11437         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11438
11439       entry->sampled = TRUE;
11440       entry->sparse = TRUE;
11441
11442       entry->caps =
11443           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11444           &codec);
11445       if (codec) {
11446         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11447             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11448         g_free (codec);
11449         codec = NULL;
11450       }
11451
11452       /* hunt for sort-of codec data */
11453       switch (fourcc) {
11454         case FOURCC_mp4s:
11455         {
11456           GNode *mp4s = NULL;
11457           GNode *esds = NULL;
11458
11459           /* look for palette in a stsd->mp4s->esds sub-atom */
11460           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11461           if (mp4s)
11462             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11463           if (esds == NULL) {
11464             /* Invalid STSD */
11465             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11466             break;
11467           }
11468
11469           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11470               stream->stream_tags);
11471           break;
11472         }
11473         default:
11474           GST_INFO_OBJECT (qtdemux,
11475               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11476           break;
11477       }
11478       GST_INFO_OBJECT (qtdemux,
11479           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11480           GST_FOURCC_ARGS (fourcc), entry->caps);
11481     } else {
11482       /* everything in 1 sample */
11483       entry->sampled = TRUE;
11484
11485       entry->caps =
11486           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11487           &codec);
11488
11489       if (entry->caps == NULL)
11490         goto unknown_stream;
11491
11492       if (codec) {
11493         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11494             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11495         g_free (codec);
11496         codec = NULL;
11497       }
11498     }
11499
11500     /* promote to sampled format */
11501     if (entry->fourcc == FOURCC_samr) {
11502       /* force mono 8000 Hz for AMR */
11503       entry->sampled = TRUE;
11504       entry->n_channels = 1;
11505       entry->rate = 8000;
11506     } else if (entry->fourcc == FOURCC_sawb) {
11507       /* force mono 16000 Hz for AMR-WB */
11508       entry->sampled = TRUE;
11509       entry->n_channels = 1;
11510       entry->rate = 16000;
11511     } else if (entry->fourcc == FOURCC_mp4a) {
11512       entry->sampled = TRUE;
11513     }
11514
11515
11516     stsd_entry_data += len;
11517     remaining_stsd_len -= len;
11518
11519   }
11520
11521   /* collect sample information */
11522   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11523     goto samples_failed;
11524
11525   if (qtdemux->fragmented) {
11526     guint64 offset;
11527
11528     /* need all moov samples as basis; probably not many if any at all */
11529     /* prevent moof parsing taking of at this time */
11530     offset = qtdemux->moof_offset;
11531     qtdemux->moof_offset = 0;
11532     if (stream->n_samples &&
11533         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11534       qtdemux->moof_offset = offset;
11535       goto samples_failed;
11536     }
11537     qtdemux->moof_offset = 0;
11538     /* movie duration more reliable in this case (e.g. mehd) */
11539     if (qtdemux->segment.duration &&
11540         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11541       stream->duration =
11542           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11543   }
11544
11545   /* configure segments */
11546   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11547     goto segments_failed;
11548
11549   /* add some language tag, if useful */
11550   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11551       strcmp (stream->lang_id, "und")) {
11552     const gchar *lang_code;
11553
11554     /* convert ISO 639-2 code to ISO 639-1 */
11555     lang_code = gst_tag_get_language_code (stream->lang_id);
11556     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11557         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11558   }
11559
11560   /* Check for UDTA tags */
11561   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11562     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11563   }
11564
11565   /* now we are ready to add the stream */
11566   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11567     goto too_many_streams;
11568
11569   if (!qtdemux->got_moov) {
11570     qtdemux->streams[qtdemux->n_streams] = stream;
11571     qtdemux->n_streams++;
11572     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11573   }
11574
11575   return TRUE;
11576
11577 /* ERRORS */
11578 skip_track:
11579   {
11580     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11581     if (new_stream)
11582       gst_qtdemux_stream_free (qtdemux, stream);
11583     return TRUE;
11584   }
11585 corrupt_file:
11586   {
11587     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11588         (_("This file is corrupt and cannot be played.")), (NULL));
11589     if (new_stream)
11590       gst_qtdemux_stream_free (qtdemux, stream);
11591     return FALSE;
11592   }
11593 error_encrypted:
11594   {
11595     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11596     if (new_stream)
11597       gst_qtdemux_stream_free (qtdemux, stream);
11598     return FALSE;
11599   }
11600 samples_failed:
11601 segments_failed:
11602   {
11603     /* we posted an error already */
11604     /* free stbl sub-atoms */
11605     gst_qtdemux_stbl_free (stream);
11606     if (new_stream)
11607       gst_qtdemux_stream_free (qtdemux, stream);
11608     return FALSE;
11609   }
11610 existing_stream:
11611   {
11612     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11613         track_id);
11614     if (new_stream)
11615       gst_qtdemux_stream_free (qtdemux, stream);
11616     return TRUE;
11617   }
11618 unknown_stream:
11619   {
11620     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11621         GST_FOURCC_ARGS (stream->subtype));
11622     if (new_stream)
11623       gst_qtdemux_stream_free (qtdemux, stream);
11624     return TRUE;
11625   }
11626 too_many_streams:
11627   {
11628     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11629         (_("This file contains too many streams. Only playing first %d"),
11630             GST_QTDEMUX_MAX_STREAMS), (NULL));
11631     return TRUE;
11632   }
11633 }
11634
11635 /* If we can estimate the overall bitrate, and don't have information about the
11636  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11637  * the overall bitrate minus the sum of the bitrates of all other streams. This
11638  * should be useful for the common case where we have one audio and one video
11639  * stream and can estimate the bitrate of one, but not the other. */
11640 static void
11641 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11642 {
11643   QtDemuxStream *stream = NULL;
11644   gint64 size, sys_bitrate, sum_bitrate = 0;
11645   GstClockTime duration;
11646   gint i;
11647   guint bitrate;
11648
11649   if (qtdemux->fragmented)
11650     return;
11651
11652   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11653
11654   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11655       || size <= 0) {
11656     GST_DEBUG_OBJECT (qtdemux,
11657         "Size in bytes of the stream not known - bailing");
11658     return;
11659   }
11660
11661   /* Subtract the header size */
11662   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11663       size, qtdemux->header_size);
11664
11665   if (size < qtdemux->header_size)
11666     return;
11667
11668   size = size - qtdemux->header_size;
11669
11670   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11671     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11672     return;
11673   }
11674
11675   for (i = 0; i < qtdemux->n_streams; i++) {
11676     switch (qtdemux->streams[i]->subtype) {
11677       case FOURCC_soun:
11678       case FOURCC_vide:
11679         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11680             CUR_STREAM (qtdemux->streams[i])->caps);
11681         /* retrieve bitrate, prefer avg then max */
11682         bitrate = 0;
11683         if (qtdemux->streams[i]->stream_tags) {
11684           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11685               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11686           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11687           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11688               GST_TAG_NOMINAL_BITRATE, &bitrate);
11689           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11690           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11691               GST_TAG_BITRATE, &bitrate);
11692           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11693         }
11694         if (bitrate)
11695           sum_bitrate += bitrate;
11696         else {
11697           if (stream) {
11698             GST_DEBUG_OBJECT (qtdemux,
11699                 ">1 stream with unknown bitrate - bailing");
11700             return;
11701           } else
11702             stream = qtdemux->streams[i];
11703         }
11704
11705       default:
11706         /* For other subtypes, we assume no significant impact on bitrate */
11707         break;
11708     }
11709   }
11710
11711   if (!stream) {
11712     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11713     return;
11714   }
11715
11716   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11717
11718   if (sys_bitrate < sum_bitrate) {
11719     /* This can happen, since sum_bitrate might be derived from maximum
11720      * bitrates and not average bitrates */
11721     GST_DEBUG_OBJECT (qtdemux,
11722         "System bitrate less than sum bitrate - bailing");
11723     return;
11724   }
11725
11726   bitrate = sys_bitrate - sum_bitrate;
11727   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11728       ", Stream bitrate = %u", sys_bitrate, bitrate);
11729
11730   if (!stream->stream_tags)
11731     stream->stream_tags = gst_tag_list_new_empty ();
11732   else
11733     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11734
11735   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11736       GST_TAG_BITRATE, bitrate, NULL);
11737 }
11738
11739 static GstFlowReturn
11740 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11741 {
11742   gint i;
11743   GstFlowReturn ret = GST_FLOW_OK;
11744
11745   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11746
11747   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11748     QtDemuxStream *stream = qtdemux->streams[i];
11749     guint32 sample_num = 0;
11750
11751     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11752         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11753
11754     if (qtdemux->fragmented) {
11755       /* need all moov samples first */
11756       GST_OBJECT_LOCK (qtdemux);
11757       while (stream->n_samples == 0)
11758         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11759           break;
11760       GST_OBJECT_UNLOCK (qtdemux);
11761     } else {
11762       /* discard any stray moof */
11763       qtdemux->moof_offset = 0;
11764     }
11765
11766     /* prepare braking */
11767     if (ret != GST_FLOW_ERROR)
11768       ret = GST_FLOW_OK;
11769
11770     /* in pull mode, we should have parsed some sample info by now;
11771      * and quite some code will not handle no samples.
11772      * in push mode, we'll just have to deal with it */
11773     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11774       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11775       gst_qtdemux_remove_stream (qtdemux, i);
11776       i--;
11777       continue;
11778     }
11779
11780     /* parse the initial sample for use in setting the frame rate cap */
11781     while (sample_num == 0 && sample_num < stream->n_samples) {
11782       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11783         break;
11784       ++sample_num;
11785     }
11786     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11787       stream->first_duration = stream->samples[0].duration;
11788       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11789           stream->track_id, stream->first_duration);
11790     }
11791   }
11792
11793   return ret;
11794 }
11795
11796 static GstFlowReturn
11797 qtdemux_expose_streams (GstQTDemux * qtdemux)
11798 {
11799   gint i;
11800   GSList *oldpads = NULL;
11801   GSList *iter;
11802
11803   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11804
11805   for (i = 0; i < qtdemux->n_streams; i++) {
11806     QtDemuxStream *stream = qtdemux->streams[i];
11807     GstPad *oldpad = stream->pad;
11808     GstTagList *list;
11809
11810     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11811         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11812
11813     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11814         stream->track_id == qtdemux->chapters_track_id) {
11815       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11816          so that it doesn't look like a subtitle track */
11817       gst_qtdemux_remove_stream (qtdemux, i);
11818       i--;
11819       continue;
11820     }
11821
11822     /* now we have all info and can expose */
11823     list = stream->stream_tags;
11824     stream->stream_tags = NULL;
11825     if (oldpad)
11826       oldpads = g_slist_prepend (oldpads, oldpad);
11827     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11828       return GST_FLOW_ERROR;
11829   }
11830
11831   gst_qtdemux_guess_bitrate (qtdemux);
11832
11833   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11834
11835   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11836     GstPad *oldpad = iter->data;
11837     GstEvent *event;
11838
11839     event = gst_event_new_eos ();
11840     if (qtdemux->segment_seqnum)
11841       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11842
11843     gst_pad_push_event (oldpad, event);
11844     gst_pad_set_active (oldpad, FALSE);
11845     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11846     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11847     gst_object_unref (oldpad);
11848   }
11849
11850   /* check if we should post a redirect in case there is a single trak
11851    * and it is a redirecting trak */
11852   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11853     GstMessage *m;
11854
11855     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11856         "an external content");
11857     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11858         gst_structure_new ("redirect",
11859             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11860             NULL));
11861     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11862     qtdemux->posted_redirect = TRUE;
11863   }
11864
11865   for (i = 0; i < qtdemux->n_streams; i++) {
11866     QtDemuxStream *stream = qtdemux->streams[i];
11867
11868     qtdemux_do_allocation (qtdemux, stream);
11869   }
11870
11871   qtdemux->exposed = TRUE;
11872   return GST_FLOW_OK;
11873 }
11874
11875 /* check if major or compatible brand is 3GP */
11876 static inline gboolean
11877 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11878 {
11879   if (major) {
11880     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11881         FOURCC_3g__);
11882   } else if (qtdemux->comp_brands != NULL) {
11883     GstMapInfo map;
11884     guint8 *data;
11885     gsize size;
11886     gboolean res = FALSE;
11887
11888     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11889     data = map.data;
11890     size = map.size;
11891     while (size >= 4) {
11892       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11893           FOURCC_3g__);
11894       data += 4;
11895       size -= 4;
11896     }
11897     gst_buffer_unmap (qtdemux->comp_brands, &map);
11898     return res;
11899   } else {
11900     return FALSE;
11901   }
11902 }
11903
11904 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11905 static inline gboolean
11906 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11907 {
11908   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11909       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11910       || fourcc == FOURCC_albm;
11911 }
11912
11913 static void
11914 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11915     const char *tag, const char *dummy, GNode * node)
11916 {
11917   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11918   int offset;
11919   char *name;
11920   gchar *data;
11921   gdouble longitude, latitude, altitude;
11922   gint len;
11923
11924   len = QT_UINT32 (node->data);
11925   if (len <= 14)
11926     goto short_read;
11927
11928   data = node->data;
11929   offset = 14;
11930
11931   /* TODO: language code skipped */
11932
11933   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11934
11935   if (!name) {
11936     /* do not alarm in trivial case, but bail out otherwise */
11937     if (*(data + offset) != 0) {
11938       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11939           "giving up", tag);
11940     }
11941   } else {
11942     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11943         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11944     offset += strlen (name);
11945     g_free (name);
11946   }
11947
11948   if (len < offset + 2 + 4 + 4 + 4)
11949     goto short_read;
11950
11951   /* +1 +1 = skip null-terminator and location role byte */
11952   offset += 1 + 1;
11953   /* table in spec says unsigned, semantics say negative has meaning ... */
11954   longitude = QT_SFP32 (data + offset);
11955
11956   offset += 4;
11957   latitude = QT_SFP32 (data + offset);
11958
11959   offset += 4;
11960   altitude = QT_SFP32 (data + offset);
11961
11962   /* one invalid means all are invalid */
11963   if (longitude >= -180.0 && longitude <= 180.0 &&
11964       latitude >= -90.0 && latitude <= 90.0) {
11965     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11966         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
11967         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
11968         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
11969   }
11970
11971   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
11972
11973   return;
11974
11975   /* ERRORS */
11976 short_read:
11977   {
11978     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
11979     return;
11980   }
11981 }
11982
11983
11984 static void
11985 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
11986     const char *tag, const char *dummy, GNode * node)
11987 {
11988   guint16 y;
11989   GDate *date;
11990   gint len;
11991
11992   len = QT_UINT32 (node->data);
11993   if (len < 14)
11994     return;
11995
11996   y = QT_UINT16 ((guint8 *) node->data + 12);
11997   if (y == 0) {
11998     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
11999     return;
12000   }
12001   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12002
12003   date = g_date_new_dmy (1, 1, y);
12004   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12005   g_date_free (date);
12006 }
12007
12008 static void
12009 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12010     const char *tag, const char *dummy, GNode * node)
12011 {
12012   int offset;
12013   char *tag_str = NULL;
12014   guint8 *entity;
12015   guint16 table;
12016   gint len;
12017
12018   len = QT_UINT32 (node->data);
12019   if (len <= 20)
12020     goto short_read;
12021
12022   offset = 12;
12023   entity = (guint8 *) node->data + offset;
12024   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12025     GST_DEBUG_OBJECT (qtdemux,
12026         "classification info: %c%c%c%c invalid classification entity",
12027         entity[0], entity[1], entity[2], entity[3]);
12028     return;
12029   }
12030
12031   offset += 4;
12032   table = QT_UINT16 ((guint8 *) node->data + offset);
12033
12034   /* Language code skipped */
12035
12036   offset += 4;
12037
12038   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12039    * XXXX: classification entity, fixed length 4 chars.
12040    * Y[YYYY]: classification table, max 5 chars.
12041    */
12042   tag_str = g_strdup_printf ("----://%u/%s",
12043       table, (char *) node->data + offset);
12044
12045   /* memcpy To be sure we're preserving byte order */
12046   memcpy (tag_str, entity, 4);
12047   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12048
12049   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12050
12051   g_free (tag_str);
12052
12053   return;
12054
12055   /* ERRORS */
12056 short_read:
12057   {
12058     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12059     return;
12060   }
12061 }
12062
12063 static gboolean
12064 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12065     const char *tag, const char *dummy, GNode * node)
12066 {
12067   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12068   GNode *data;
12069   char *s;
12070   int len;
12071   guint32 type;
12072   int offset;
12073   gboolean ret = TRUE;
12074   const gchar *charset = NULL;
12075
12076   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12077   if (data) {
12078     len = QT_UINT32 (data->data);
12079     type = QT_UINT32 ((guint8 *) data->data + 8);
12080     if (type == 0x00000001 && len > 16) {
12081       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12082           env_vars);
12083       if (s) {
12084         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12085         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12086         g_free (s);
12087       } else {
12088         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12089       }
12090     }
12091   } else {
12092     len = QT_UINT32 (node->data);
12093     type = QT_UINT32 ((guint8 *) node->data + 4);
12094     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12095       gint str_len;
12096       gint lang_code;
12097
12098       /* Type starts with the (C) symbol, so the next data is a list
12099        * of (string size(16), language code(16), string) */
12100
12101       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12102       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12103
12104       /* the string + fourcc + size + 2 16bit fields,
12105        * means that there are more tags in this atom */
12106       if (len > str_len + 8 + 4) {
12107         /* TODO how to represent the same tag in different languages? */
12108         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12109             "text alternatives, reading only first one");
12110       }
12111
12112       offset = 12;
12113       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12114       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12115
12116       if (lang_code < 0x800) {  /* MAC encoded string */
12117         charset = "mac";
12118       }
12119     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12120             QT_FOURCC ((guint8 *) node->data + 4))) {
12121       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12122
12123       /* we go for 3GP style encoding if major brands claims so,
12124        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12125       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12126           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12127               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12128         offset = 14;
12129         /* 16-bit Language code is ignored here as well */
12130         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12131       } else {
12132         goto normal;
12133       }
12134     } else {
12135     normal:
12136       offset = 8;
12137       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12138       ret = FALSE;              /* may have to fallback */
12139     }
12140     if (charset) {
12141       GError *err = NULL;
12142
12143       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12144           charset, NULL, NULL, &err);
12145       if (err) {
12146         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12147             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12148             err->message);
12149         g_error_free (err);
12150       }
12151     } else {
12152       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12153           len - offset, env_vars);
12154     }
12155     if (s) {
12156       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12157       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12158       g_free (s);
12159       ret = TRUE;
12160     } else {
12161       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12162     }
12163   }
12164   return ret;
12165 }
12166
12167 static void
12168 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12169     const char *tag, const char *dummy, GNode * node)
12170 {
12171   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12172 }
12173
12174 static void
12175 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12176     const char *tag, const char *dummy, GNode * node)
12177 {
12178   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12179   guint8 *data;
12180   char *s, *t, *k = NULL;
12181   int len;
12182   int offset;
12183   int count;
12184
12185   /* first try normal string tag if major brand not 3GP */
12186   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12187     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12188       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12189        * let's try it 3gpp way after minor safety check */
12190       data = node->data;
12191       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12192         return;
12193     } else
12194       return;
12195   }
12196
12197   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12198
12199   data = node->data;
12200
12201   len = QT_UINT32 (data);
12202   if (len < 15)
12203     goto short_read;
12204
12205   count = QT_UINT8 (data + 14);
12206   offset = 15;
12207   for (; count; count--) {
12208     gint slen;
12209
12210     if (offset + 1 > len)
12211       goto short_read;
12212     slen = QT_UINT8 (data + offset);
12213     offset += 1;
12214     if (offset + slen > len)
12215       goto short_read;
12216     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12217         slen, env_vars);
12218     if (s) {
12219       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12220       if (k) {
12221         t = g_strjoin (",", k, s, NULL);
12222         g_free (s);
12223         g_free (k);
12224         k = t;
12225       } else {
12226         k = s;
12227       }
12228     } else {
12229       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12230     }
12231     offset += slen;
12232   }
12233
12234 done:
12235   if (k) {
12236     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12237     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12238   }
12239   g_free (k);
12240
12241   return;
12242
12243   /* ERRORS */
12244 short_read:
12245   {
12246     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12247     goto done;
12248   }
12249 }
12250
12251 static void
12252 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12253     const char *tag1, const char *tag2, GNode * node)
12254 {
12255   GNode *data;
12256   int len;
12257   int type;
12258   int n1, n2;
12259
12260   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12261   if (data) {
12262     len = QT_UINT32 (data->data);
12263     type = QT_UINT32 ((guint8 *) data->data + 8);
12264     if (type == 0x00000000 && len >= 22) {
12265       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12266       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12267       if (n1 > 0) {
12268         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12269         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12270       }
12271       if (n2 > 0) {
12272         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12273         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12274       }
12275     }
12276   }
12277 }
12278
12279 static void
12280 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12281     const char *tag1, const char *dummy, GNode * node)
12282 {
12283   GNode *data;
12284   int len;
12285   int type;
12286   int n1;
12287
12288   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12289   if (data) {
12290     len = QT_UINT32 (data->data);
12291     type = QT_UINT32 ((guint8 *) data->data + 8);
12292     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12293     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12294     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12295       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12296       if (n1) {
12297         /* do not add bpm=0 */
12298         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12299         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12300             NULL);
12301       }
12302     }
12303   }
12304 }
12305
12306 static void
12307 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12308     const char *tag1, const char *dummy, GNode * node)
12309 {
12310   GNode *data;
12311   int len;
12312   int type;
12313   guint32 num;
12314
12315   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12316   if (data) {
12317     len = QT_UINT32 (data->data);
12318     type = QT_UINT32 ((guint8 *) data->data + 8);
12319     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12320     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12321     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12322       num = QT_UINT32 ((guint8 *) data->data + 16);
12323       if (num) {
12324         /* do not add num=0 */
12325         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12326         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12327       }
12328     }
12329   }
12330 }
12331
12332 static void
12333 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12334     const char *tag1, const char *dummy, GNode * node)
12335 {
12336   GNode *data;
12337   int len;
12338   int type;
12339   GstSample *sample;
12340
12341   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12342   if (data) {
12343     len = QT_UINT32 (data->data);
12344     type = QT_UINT32 ((guint8 *) data->data + 8);
12345     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12346     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12347       GstTagImageType image_type;
12348
12349       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12350         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12351       else
12352         image_type = GST_TAG_IMAGE_TYPE_NONE;
12353
12354       if ((sample =
12355               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12356                   len - 16, image_type))) {
12357         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12358         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12359         gst_sample_unref (sample);
12360       }
12361     }
12362   }
12363 }
12364
12365 static void
12366 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12367     const char *tag, const char *dummy, GNode * node)
12368 {
12369   GNode *data;
12370   char *s;
12371   int len;
12372   int type;
12373
12374   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12375   if (data) {
12376     len = QT_UINT32 (data->data);
12377     type = QT_UINT32 ((guint8 *) data->data + 8);
12378     if (type == 0x00000001 && len > 16) {
12379       guint y, m = 1, d = 1;
12380       gint ret;
12381
12382       s = g_strndup ((char *) data->data + 16, len - 16);
12383       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12384       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12385       if (ret >= 1 && y > 1500 && y < 3000) {
12386         GDate *date;
12387
12388         date = g_date_new_dmy (d, m, y);
12389         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12390         g_date_free (date);
12391       } else {
12392         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12393       }
12394       g_free (s);
12395     }
12396   }
12397 }
12398
12399 static void
12400 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12401     const char *tag, const char *dummy, GNode * node)
12402 {
12403   GNode *data;
12404
12405   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12406
12407   /* re-route to normal string tag if major brand says so
12408    * or no data atom and compatible brand suggests so */
12409   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12410       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12411     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12412     return;
12413   }
12414
12415   if (data) {
12416     guint len, type, n;
12417
12418     len = QT_UINT32 (data->data);
12419     type = QT_UINT32 ((guint8 *) data->data + 8);
12420     if (type == 0x00000000 && len >= 18) {
12421       n = QT_UINT16 ((guint8 *) data->data + 16);
12422       if (n > 0) {
12423         const gchar *genre;
12424
12425         genre = gst_tag_id3_genre_get (n - 1);
12426         if (genre != NULL) {
12427           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12428           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12429         }
12430       }
12431     }
12432   }
12433 }
12434
12435 static void
12436 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12437     const gchar * tag, guint8 * data, guint32 datasize)
12438 {
12439   gdouble value;
12440   gchar *datacopy;
12441
12442   /* make a copy to have \0 at the end */
12443   datacopy = g_strndup ((gchar *) data, datasize);
12444
12445   /* convert the str to double */
12446   if (sscanf (datacopy, "%lf", &value) == 1) {
12447     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12448     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12449   } else {
12450     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12451         datacopy);
12452   }
12453   g_free (datacopy);
12454 }
12455
12456
12457 static void
12458 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12459     const char *tag, const char *tag_bis, GNode * node)
12460 {
12461   GNode *mean;
12462   GNode *name;
12463   GNode *data;
12464   guint32 meansize;
12465   guint32 namesize;
12466   guint32 datatype;
12467   guint32 datasize;
12468   const gchar *meanstr;
12469   const gchar *namestr;
12470
12471   /* checking the whole ---- atom size for consistency */
12472   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12473     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12474     return;
12475   }
12476
12477   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12478   if (!mean) {
12479     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12480     return;
12481   }
12482
12483   meansize = QT_UINT32 (mean->data);
12484   if (meansize <= 12) {
12485     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12486     return;
12487   }
12488   meanstr = ((gchar *) mean->data) + 12;
12489   meansize -= 12;
12490
12491   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12492   if (!name) {
12493     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12494     return;
12495   }
12496
12497   namesize = QT_UINT32 (name->data);
12498   if (namesize <= 12) {
12499     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12500     return;
12501   }
12502   namestr = ((gchar *) name->data) + 12;
12503   namesize -= 12;
12504
12505   /*
12506    * Data atom is:
12507    * uint32 - size
12508    * uint32 - name
12509    * uint8  - version
12510    * uint24 - data type
12511    * uint32 - all 0
12512    * rest   - the data
12513    */
12514   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12515   if (!data) {
12516     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12517     return;
12518   }
12519   datasize = QT_UINT32 (data->data);
12520   if (datasize <= 16) {
12521     GST_WARNING_OBJECT (demux, "Data atom too small");
12522     return;
12523   }
12524   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12525
12526   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12527       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12528     static const struct
12529     {
12530       const gchar name[28];
12531       const gchar tag[28];
12532     } tags[] = {
12533       {
12534       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12535       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12536       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12537       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12538       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12539       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12540       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12541       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12542     };
12543     int i;
12544
12545     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12546       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12547         switch (gst_tag_get_type (tags[i].tag)) {
12548           case G_TYPE_DOUBLE:
12549             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12550                 ((guint8 *) data->data) + 16, datasize - 16);
12551             break;
12552           case G_TYPE_STRING:
12553             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12554             break;
12555           default:
12556             /* not reached */
12557             break;
12558         }
12559         break;
12560       }
12561     }
12562     if (i == G_N_ELEMENTS (tags))
12563       goto unknown_tag;
12564   } else {
12565     goto unknown_tag;
12566   }
12567
12568   return;
12569
12570 /* errors */
12571 unknown_tag:
12572 #ifndef GST_DISABLE_GST_DEBUG
12573   {
12574     gchar *namestr_dbg;
12575     gchar *meanstr_dbg;
12576
12577     meanstr_dbg = g_strndup (meanstr, meansize);
12578     namestr_dbg = g_strndup (namestr, namesize);
12579
12580     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12581         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12582
12583     g_free (namestr_dbg);
12584     g_free (meanstr_dbg);
12585   }
12586 #endif
12587   return;
12588 }
12589
12590 static void
12591 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12592     const char *tag_bis, GNode * node)
12593 {
12594   guint8 *data;
12595   GstBuffer *buf;
12596   guint len;
12597   GstTagList *id32_taglist = NULL;
12598
12599   GST_LOG_OBJECT (demux, "parsing ID32");
12600
12601   data = node->data;
12602   len = GST_READ_UINT32_BE (data);
12603
12604   /* need at least full box and language tag */
12605   if (len < 12 + 2)
12606     return;
12607
12608   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12609   gst_buffer_fill (buf, 0, data + 14, len - 14);
12610
12611   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12612   if (id32_taglist) {
12613     GST_LOG_OBJECT (demux, "parsing ok");
12614     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12615     gst_tag_list_unref (id32_taglist);
12616   } else {
12617     GST_LOG_OBJECT (demux, "parsing failed");
12618   }
12619
12620   gst_buffer_unref (buf);
12621 }
12622
12623 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12624     const char *tag, const char *tag_bis, GNode * node);
12625
12626 /* unmapped tags
12627 FOURCC_pcst -> if media is a podcast -> bool
12628 FOURCC_cpil -> if media is part of a compilation -> bool
12629 FOURCC_pgap -> if media is part of a gapless context -> bool
12630 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12631 */
12632
12633 static const struct
12634 {
12635   guint32 fourcc;
12636   const gchar *gst_tag;
12637   const gchar *gst_tag_bis;
12638   const GstQTDemuxAddTagFunc func;
12639 } add_funcs[] = {
12640   {
12641   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12642   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12643   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12644   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12645   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12646   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12647   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12648   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12649   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12650   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12651   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12652   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12653   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12654   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12655   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12656   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12657   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12658   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12659   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12660   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12661   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12662   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12663   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12664         qtdemux_tag_add_num}, {
12665   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12666         qtdemux_tag_add_num}, {
12667   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12668   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12669   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12670   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12671   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12672   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12673   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12674   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12675   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12676   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12677   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12678   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12679   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12680   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12681   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12682   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12683   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12684   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12685         qtdemux_tag_add_classification}, {
12686   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12687   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12688   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12689
12690     /* This is a special case, some tags are stored in this
12691      * 'reverse dns naming', according to:
12692      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12693      * bug #614471
12694      */
12695   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12696     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12697   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12698 };
12699
12700 struct _GstQtDemuxTagList
12701 {
12702   GstQTDemux *demux;
12703   GstTagList *taglist;
12704 };
12705 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12706
12707 static void
12708 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12709 {
12710   gint len;
12711   guint8 *data;
12712   GstBuffer *buf;
12713   gchar *media_type;
12714   const gchar *style;
12715   GstSample *sample;
12716   GstStructure *s;
12717   guint i;
12718   guint8 ndata[4];
12719   GstQTDemux *demux = qtdemuxtaglist->demux;
12720   GstTagList *taglist = qtdemuxtaglist->taglist;
12721
12722   data = node->data;
12723   len = QT_UINT32 (data);
12724   buf = gst_buffer_new_and_alloc (len);
12725   gst_buffer_fill (buf, 0, data, len);
12726
12727   /* heuristic to determine style of tag */
12728   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12729       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12730     style = "itunes";
12731   else if (demux->major_brand == FOURCC_qt__)
12732     style = "quicktime";
12733   /* fall back to assuming iso/3gp tag style */
12734   else
12735     style = "iso";
12736
12737   /* santize the name for the caps. */
12738   for (i = 0; i < 4; i++) {
12739     guint8 d = data[4 + i];
12740     if (g_ascii_isalnum (d))
12741       ndata[i] = g_ascii_tolower (d);
12742     else
12743       ndata[i] = '_';
12744   }
12745
12746   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12747       ndata[0], ndata[1], ndata[2], ndata[3]);
12748   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12749
12750   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12751   sample = gst_sample_new (buf, NULL, NULL, s);
12752   gst_buffer_unref (buf);
12753   g_free (media_type);
12754
12755   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12756       len, s);
12757
12758   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12759       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12760
12761   gst_sample_unref (sample);
12762 }
12763
12764 static void
12765 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12766 {
12767   GNode *meta;
12768   GNode *ilst;
12769   GNode *xmp_;
12770   GNode *node;
12771   gint i;
12772   GstQtDemuxTagList demuxtaglist;
12773
12774   demuxtaglist.demux = qtdemux;
12775   demuxtaglist.taglist = taglist;
12776
12777   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12778   if (meta != NULL) {
12779     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12780     if (ilst == NULL) {
12781       GST_LOG_OBJECT (qtdemux, "no ilst");
12782       return;
12783     }
12784   } else {
12785     ilst = udta;
12786     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12787   }
12788
12789   i = 0;
12790   while (i < G_N_ELEMENTS (add_funcs)) {
12791     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12792     if (node) {
12793       gint len;
12794
12795       len = QT_UINT32 (node->data);
12796       if (len < 12) {
12797         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12798             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12799       } else {
12800         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12801             add_funcs[i].gst_tag_bis, node);
12802       }
12803       g_node_destroy (node);
12804     } else {
12805       i++;
12806     }
12807   }
12808
12809   /* parsed nodes have been removed, pass along remainder as blob */
12810   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12811       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12812
12813   /* parse up XMP_ node if existing */
12814   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12815   if (xmp_ != NULL) {
12816     GstBuffer *buf;
12817     GstTagList *xmptaglist;
12818
12819     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12820         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12821     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12822     gst_buffer_unref (buf);
12823
12824     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12825   } else {
12826     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12827   }
12828 }
12829
12830 typedef struct
12831 {
12832   GstStructure *structure;      /* helper for sort function */
12833   gchar *location;
12834   guint min_req_bitrate;
12835   guint min_req_qt_version;
12836 } GstQtReference;
12837
12838 static gint
12839 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12840 {
12841   GstQtReference *ref_a = (GstQtReference *) a;
12842   GstQtReference *ref_b = (GstQtReference *) b;
12843
12844   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12845     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12846
12847   /* known bitrates go before unknown; higher bitrates go first */
12848   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12849 }
12850
12851 /* sort the redirects and post a message for the application.
12852  */
12853 static void
12854 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12855 {
12856   GstQtReference *best;
12857   GstStructure *s;
12858   GstMessage *msg;
12859   GValue list_val = { 0, };
12860   GList *l;
12861
12862   g_assert (references != NULL);
12863
12864   references = g_list_sort (references, qtdemux_redirects_sort_func);
12865
12866   best = (GstQtReference *) references->data;
12867
12868   g_value_init (&list_val, GST_TYPE_LIST);
12869
12870   for (l = references; l != NULL; l = l->next) {
12871     GstQtReference *ref = (GstQtReference *) l->data;
12872     GValue struct_val = { 0, };
12873
12874     ref->structure = gst_structure_new ("redirect",
12875         "new-location", G_TYPE_STRING, ref->location, NULL);
12876
12877     if (ref->min_req_bitrate > 0) {
12878       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12879           ref->min_req_bitrate, NULL);
12880     }
12881
12882     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12883     g_value_set_boxed (&struct_val, ref->structure);
12884     gst_value_list_append_value (&list_val, &struct_val);
12885     g_value_unset (&struct_val);
12886     /* don't free anything here yet, since we need best->structure below */
12887   }
12888
12889   g_assert (best != NULL);
12890   s = gst_structure_copy (best->structure);
12891
12892   if (g_list_length (references) > 1) {
12893     gst_structure_set_value (s, "locations", &list_val);
12894   }
12895
12896   g_value_unset (&list_val);
12897
12898   for (l = references; l != NULL; l = l->next) {
12899     GstQtReference *ref = (GstQtReference *) l->data;
12900
12901     gst_structure_free (ref->structure);
12902     g_free (ref->location);
12903     g_free (ref);
12904   }
12905   g_list_free (references);
12906
12907   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12908   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12909   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12910   qtdemux->posted_redirect = TRUE;
12911 }
12912
12913 /* look for redirect nodes, collect all redirect information and
12914  * process it.
12915  */
12916 static gboolean
12917 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12918 {
12919   GNode *rmra, *rmda, *rdrf;
12920
12921   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12922   if (rmra) {
12923     GList *redirects = NULL;
12924
12925     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12926     while (rmda) {
12927       GstQtReference ref = { NULL, NULL, 0, 0 };
12928       GNode *rmdr, *rmvc;
12929
12930       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12931         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12932         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12933             ref.min_req_bitrate);
12934       }
12935
12936       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12937         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12938         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12939
12940 #ifndef GST_DISABLE_GST_DEBUG
12941         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12942 #endif
12943         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12944
12945         GST_LOG_OBJECT (qtdemux,
12946             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12947             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12948             bitmask, check_type);
12949         if (package == FOURCC_qtim && check_type == 0) {
12950           ref.min_req_qt_version = version;
12951         }
12952       }
12953
12954       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12955       if (rdrf) {
12956         guint32 ref_type;
12957         guint8 *ref_data;
12958         guint ref_len;
12959
12960         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12961         if (ref_len > 20) {
12962           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
12963           ref_data = (guint8 *) rdrf->data + 20;
12964           if (ref_type == FOURCC_alis) {
12965             guint record_len, record_version, fn_len;
12966
12967             if (ref_len > 70) {
12968               /* MacOSX alias record, google for alias-layout.txt */
12969               record_len = QT_UINT16 (ref_data + 4);
12970               record_version = QT_UINT16 (ref_data + 4 + 2);
12971               fn_len = QT_UINT8 (ref_data + 50);
12972               if (record_len > 50 && record_version == 2 && fn_len > 0) {
12973                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
12974               }
12975             } else {
12976               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
12977                   ref_len);
12978             }
12979           } else if (ref_type == FOURCC_url_) {
12980             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
12981           } else {
12982             GST_DEBUG_OBJECT (qtdemux,
12983                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
12984                 GST_FOURCC_ARGS (ref_type));
12985           }
12986           if (ref.location != NULL) {
12987             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
12988             redirects =
12989                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
12990           } else {
12991             GST_WARNING_OBJECT (qtdemux,
12992                 "Failed to extract redirect location from rdrf atom");
12993           }
12994         } else {
12995           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
12996         }
12997       }
12998
12999       /* look for others */
13000       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13001     }
13002
13003     if (redirects != NULL) {
13004       qtdemux_process_redirects (qtdemux, redirects);
13005     }
13006   }
13007   return TRUE;
13008 }
13009
13010 static GstTagList *
13011 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13012 {
13013   const gchar *fmt;
13014
13015   if (tags == NULL) {
13016     tags = gst_tag_list_new_empty ();
13017     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13018   }
13019
13020   if (qtdemux->major_brand == FOURCC_mjp2)
13021     fmt = "Motion JPEG 2000";
13022   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13023     fmt = "3GP";
13024   else if (qtdemux->major_brand == FOURCC_qt__)
13025     fmt = "Quicktime";
13026   else if (qtdemux->fragmented)
13027     fmt = "ISO fMP4";
13028   else
13029     fmt = "ISO MP4/M4A";
13030
13031   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13032       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13033
13034   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13035       fmt, NULL);
13036
13037   return tags;
13038 }
13039
13040 /* we have read the complete moov node now.
13041  * This function parses all of the relevant info, creates the traks and
13042  * prepares all data structures for playback
13043  */
13044 static gboolean
13045 qtdemux_parse_tree (GstQTDemux * qtdemux)
13046 {
13047   GNode *mvhd;
13048   GNode *trak;
13049   GNode *udta;
13050   GNode *mvex;
13051   GstClockTime duration;
13052   GNode *pssh;
13053   guint64 creation_time;
13054   GstDateTime *datetime = NULL;
13055   gint version;
13056
13057   /* make sure we have a usable taglist */
13058   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13059
13060   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13061   if (mvhd == NULL) {
13062     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13063     return qtdemux_parse_redirects (qtdemux);
13064   }
13065
13066   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13067   if (version == 1) {
13068     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13069     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13070     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13071   } else if (version == 0) {
13072     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13073     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13074     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13075   } else {
13076     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13077     return FALSE;
13078   }
13079
13080   /* Moving qt creation time (secs since 1904) to unix time */
13081   if (creation_time != 0) {
13082     /* Try to use epoch first as it should be faster and more commonly found */
13083     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13084       GTimeVal now;
13085
13086       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13087       /* some data cleansing sanity */
13088       g_get_current_time (&now);
13089       if (now.tv_sec + 24 * 3600 < creation_time) {
13090         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13091       } else {
13092         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13093       }
13094     } else {
13095       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13096       GDateTime *dt, *dt_local;
13097
13098       dt = g_date_time_add_seconds (base_dt, creation_time);
13099       dt_local = g_date_time_to_local (dt);
13100       datetime = gst_date_time_new_from_g_date_time (dt_local);
13101
13102       g_date_time_unref (base_dt);
13103       g_date_time_unref (dt);
13104     }
13105   }
13106   if (datetime) {
13107     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13108     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13109         datetime, NULL);
13110     gst_date_time_unref (datetime);
13111   }
13112
13113   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13114   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13115
13116   /* check for fragmented file and get some (default) data */
13117   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13118   if (mvex) {
13119     GNode *mehd;
13120     GstByteReader mehd_data;
13121
13122     /* let track parsing or anyone know weird stuff might happen ... */
13123     qtdemux->fragmented = TRUE;
13124
13125     /* compensate for total duration */
13126     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13127     if (mehd)
13128       qtdemux_parse_mehd (qtdemux, &mehd_data);
13129   }
13130
13131   /* set duration in the segment info */
13132   gst_qtdemux_get_duration (qtdemux, &duration);
13133   if (duration) {
13134     qtdemux->segment.duration = duration;
13135     /* also do not exceed duration; stop is set that way post seek anyway,
13136      * and segment activation falls back to duration,
13137      * whereas loop only checks stop, so let's align this here as well */
13138     qtdemux->segment.stop = duration;
13139   }
13140
13141   /* parse all traks */
13142   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13143   while (trak) {
13144     qtdemux_parse_trak (qtdemux, trak);
13145     /* iterate all siblings */
13146     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13147   }
13148
13149   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13150
13151   /* find tags */
13152   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13153   if (udta) {
13154     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13155   } else {
13156     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13157   }
13158
13159   /* maybe also some tags in meta box */
13160   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13161   if (udta) {
13162     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13163     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13164   } else {
13165     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13166   }
13167
13168   /* parse any protection system info */
13169   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13170   while (pssh) {
13171     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13172     qtdemux_parse_pssh (qtdemux, pssh);
13173     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13174   }
13175
13176   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13177
13178   return TRUE;
13179 }
13180
13181 /* taken from ffmpeg */
13182 static int
13183 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13184 {
13185   int count = 4;
13186   int len = 0;
13187
13188   while (count--) {
13189     int c;
13190
13191     if (ptr >= end)
13192       return -1;
13193
13194     c = *ptr++;
13195     len = (len << 7) | (c & 0x7f);
13196     if (!(c & 0x80))
13197       break;
13198   }
13199   *end_out = ptr;
13200   return len;
13201 }
13202
13203 /* this can change the codec originally present in @list */
13204 static void
13205 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13206     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13207 {
13208   int len = QT_UINT32 (esds->data);
13209   guint8 *ptr = esds->data;
13210   guint8 *end = ptr + len;
13211   int tag;
13212   guint8 *data_ptr = NULL;
13213   int data_len = 0;
13214   guint8 object_type_id = 0;
13215   const char *codec_name = NULL;
13216   GstCaps *caps = NULL;
13217
13218   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13219   ptr += 8;
13220   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13221   ptr += 4;
13222   while (ptr + 1 < end) {
13223     tag = QT_UINT8 (ptr);
13224     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13225     ptr++;
13226     len = read_descr_size (ptr, end, &ptr);
13227     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13228
13229     /* Check the stated amount of data is available for reading */
13230     if (len < 0 || ptr + len > end)
13231       break;
13232
13233     switch (tag) {
13234       case ES_DESCRIPTOR_TAG:
13235         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13236         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13237         ptr += 3;
13238         break;
13239       case DECODER_CONFIG_DESC_TAG:{
13240         guint max_bitrate, avg_bitrate;
13241
13242         object_type_id = QT_UINT8 (ptr);
13243         max_bitrate = QT_UINT32 (ptr + 5);
13244         avg_bitrate = QT_UINT32 (ptr + 9);
13245         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13246         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13247         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13248         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13249         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13250         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13251           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13252               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13253         }
13254         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13255           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13256               avg_bitrate, NULL);
13257         }
13258         ptr += 13;
13259         break;
13260       }
13261       case DECODER_SPECIFIC_INFO_TAG:
13262         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13263         if (object_type_id == 0xe0 && len == 0x40) {
13264           guint8 *data;
13265           GstStructure *s;
13266           guint32 clut[16];
13267           gint i;
13268
13269           GST_DEBUG_OBJECT (qtdemux,
13270               "Have VOBSUB palette. Creating palette event");
13271           /* move to decConfigDescr data and read palette */
13272           data = ptr;
13273           for (i = 0; i < 16; i++) {
13274             clut[i] = QT_UINT32 (data);
13275             data += 4;
13276           }
13277
13278           s = gst_structure_new ("application/x-gst-dvd", "event",
13279               G_TYPE_STRING, "dvd-spu-clut-change",
13280               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13281               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13282               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13283               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13284               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13285               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13286               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13287               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13288               NULL);
13289
13290           /* store event and trigger custom processing */
13291           stream->pending_event =
13292               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13293         } else {
13294           /* Generic codec_data handler puts it on the caps */
13295           data_ptr = ptr;
13296           data_len = len;
13297         }
13298
13299         ptr += len;
13300         break;
13301       case SL_CONFIG_DESC_TAG:
13302         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13303         ptr += 1;
13304         break;
13305       default:
13306         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13307             tag);
13308         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13309         ptr += len;
13310         break;
13311     }
13312   }
13313
13314   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13315    * in use, and should also be used to override some other parameters for some
13316    * codecs. */
13317   switch (object_type_id) {
13318     case 0x20:                 /* MPEG-4 */
13319       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13320        * profile_and_level_indication */
13321       if (data_ptr != NULL && data_len >= 5 &&
13322           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13323         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13324             data_ptr + 4, data_len - 4);
13325       }
13326       break;                    /* Nothing special needed here */
13327     case 0x21:                 /* H.264 */
13328       codec_name = "H.264 / AVC";
13329       caps = gst_caps_new_simple ("video/x-h264",
13330           "stream-format", G_TYPE_STRING, "avc",
13331           "alignment", G_TYPE_STRING, "au", NULL);
13332       break;
13333     case 0x40:                 /* AAC (any) */
13334     case 0x66:                 /* AAC Main */
13335     case 0x67:                 /* AAC LC */
13336     case 0x68:                 /* AAC SSR */
13337       /* Override channels and rate based on the codec_data, as it's often
13338        * wrong. */
13339       /* Only do so for basic setup without HE-AAC extension */
13340       if (data_ptr && data_len == 2) {
13341         guint channels, rate;
13342
13343         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13344         if (channels > 0)
13345           entry->n_channels = channels;
13346
13347         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13348         if (rate > 0)
13349           entry->rate = rate;
13350       }
13351
13352       /* Set level and profile if possible */
13353       if (data_ptr != NULL && data_len >= 2) {
13354         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13355             data_ptr, data_len);
13356       } else {
13357         const gchar *profile_str = NULL;
13358         GstBuffer *buffer;
13359         GstMapInfo map;
13360         guint8 *codec_data;
13361         gint rate_idx, profile;
13362
13363         /* No codec_data, let's invent something.
13364          * FIXME: This is wrong for SBR! */
13365
13366         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13367
13368         buffer = gst_buffer_new_and_alloc (2);
13369         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13370         codec_data = map.data;
13371
13372         rate_idx =
13373             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13374             (stream)->rate);
13375
13376         switch (object_type_id) {
13377           case 0x66:
13378             profile_str = "main";
13379             profile = 0;
13380             break;
13381           case 0x67:
13382             profile_str = "lc";
13383             profile = 1;
13384             break;
13385           case 0x68:
13386             profile_str = "ssr";
13387             profile = 2;
13388             break;
13389           default:
13390             profile = 3;
13391             break;
13392         }
13393
13394         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13395         codec_data[1] =
13396             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13397
13398         gst_buffer_unmap (buffer, &map);
13399         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13400             GST_TYPE_BUFFER, buffer, NULL);
13401         gst_buffer_unref (buffer);
13402
13403         if (profile_str) {
13404           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13405               G_TYPE_STRING, profile_str, NULL);
13406         }
13407       }
13408       break;
13409     case 0x60:                 /* MPEG-2, various profiles */
13410     case 0x61:
13411     case 0x62:
13412     case 0x63:
13413     case 0x64:
13414     case 0x65:
13415       codec_name = "MPEG-2 video";
13416       caps = gst_caps_new_simple ("video/mpeg",
13417           "mpegversion", G_TYPE_INT, 2,
13418           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13419       break;
13420     case 0x69:                 /* MPEG-2 BC audio */
13421     case 0x6B:                 /* MPEG-1 audio */
13422       caps = gst_caps_new_simple ("audio/mpeg",
13423           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13424       codec_name = "MPEG-1 audio";
13425       break;
13426     case 0x6A:                 /* MPEG-1 */
13427       codec_name = "MPEG-1 video";
13428       caps = gst_caps_new_simple ("video/mpeg",
13429           "mpegversion", G_TYPE_INT, 1,
13430           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13431       break;
13432     case 0x6C:                 /* MJPEG */
13433       caps =
13434           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13435           NULL);
13436       codec_name = "Motion-JPEG";
13437       break;
13438     case 0x6D:                 /* PNG */
13439       caps =
13440           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13441           NULL);
13442       codec_name = "PNG still images";
13443       break;
13444     case 0x6E:                 /* JPEG2000 */
13445       codec_name = "JPEG-2000";
13446       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13447       break;
13448     case 0xA4:                 /* Dirac */
13449       codec_name = "Dirac";
13450       caps = gst_caps_new_empty_simple ("video/x-dirac");
13451       break;
13452     case 0xA5:                 /* AC3 */
13453       codec_name = "AC-3 audio";
13454       caps = gst_caps_new_simple ("audio/x-ac3",
13455           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13456       break;
13457     case 0xA9:                 /* AC3 */
13458       codec_name = "DTS audio";
13459       caps = gst_caps_new_simple ("audio/x-dts",
13460           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13461       break;
13462     case 0xE1:                 /* QCELP */
13463       /* QCELP, the codec_data is a riff tag (little endian) with
13464        * 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). */
13465       caps = gst_caps_new_empty_simple ("audio/qcelp");
13466       codec_name = "QCELP";
13467       break;
13468     default:
13469       break;
13470   }
13471
13472   /* If we have a replacement caps, then change our caps for this stream */
13473   if (caps) {
13474     gst_caps_unref (entry->caps);
13475     entry->caps = caps;
13476   }
13477
13478   if (codec_name && list)
13479     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13480         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13481
13482   /* Add the codec_data attribute to caps, if we have it */
13483   if (data_ptr) {
13484     GstBuffer *buffer;
13485
13486     buffer = gst_buffer_new_and_alloc (data_len);
13487     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13488
13489     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13490     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13491
13492     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13493         buffer, NULL);
13494     gst_buffer_unref (buffer);
13495   }
13496
13497 }
13498
13499 static inline GstCaps *
13500 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13501 {
13502   GstCaps *caps;
13503   guint i;
13504   char *s, fourstr[5];
13505
13506   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13507   for (i = 0; i < 4; i++) {
13508     if (!g_ascii_isalnum (fourstr[i]))
13509       fourstr[i] = '_';
13510   }
13511   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13512   caps = gst_caps_new_empty_simple (s);
13513   g_free (s);
13514   return caps;
13515 }
13516
13517 #define _codec(name) \
13518   do { \
13519     if (codec_name) { \
13520       *codec_name = g_strdup (name); \
13521     } \
13522   } while (0)
13523
13524 static GstCaps *
13525 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13526     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13527     const guint8 * stsd_entry_data, gchar ** codec_name)
13528 {
13529   GstCaps *caps = NULL;
13530   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13531
13532   switch (fourcc) {
13533     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
13534       _codec ("PNG still images");
13535       caps = gst_caps_new_empty_simple ("image/png");
13536       break;
13537     case FOURCC_jpeg:
13538       _codec ("JPEG still images");
13539       caps =
13540           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13541           NULL);
13542       break;
13543     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13544     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13545     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13546     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13547       _codec ("Motion-JPEG");
13548       caps =
13549           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13550           NULL);
13551       break;
13552     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13553       _codec ("Motion-JPEG format B");
13554       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13555       break;
13556     case FOURCC_mjp2:
13557       _codec ("JPEG-2000");
13558       /* override to what it should be according to spec, avoid palette_data */
13559       entry->bits_per_sample = 24;
13560       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13561       break;
13562     case FOURCC_SVQ3:
13563       _codec ("Sorensen video v.3");
13564       caps = gst_caps_new_simple ("video/x-svq",
13565           "svqversion", G_TYPE_INT, 3, NULL);
13566       break;
13567     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13568     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13569       _codec ("Sorensen video v.1");
13570       caps = gst_caps_new_simple ("video/x-svq",
13571           "svqversion", G_TYPE_INT, 1, NULL);
13572       break;
13573     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13574       caps = gst_caps_new_empty_simple ("video/x-raw");
13575       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13576       _codec ("Windows Raw RGB");
13577       stream->alignment = 32;
13578       break;
13579     case FOURCC_raw_:
13580     {
13581       guint16 bps;
13582
13583       bps = QT_UINT16 (stsd_entry_data + 82);
13584       switch (bps) {
13585         case 15:
13586           format = GST_VIDEO_FORMAT_RGB15;
13587           break;
13588         case 16:
13589           format = GST_VIDEO_FORMAT_RGB16;
13590           break;
13591         case 24:
13592           format = GST_VIDEO_FORMAT_RGB;
13593           break;
13594         case 32:
13595           format = GST_VIDEO_FORMAT_ARGB;
13596           break;
13597         default:
13598           /* unknown */
13599           break;
13600       }
13601       break;
13602     }
13603     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13604       format = GST_VIDEO_FORMAT_I420;
13605       break;
13606     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13607     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13608       format = GST_VIDEO_FORMAT_I420;
13609       break;
13610     case FOURCC_2vuy:
13611     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13612       format = GST_VIDEO_FORMAT_UYVY;
13613       break;
13614     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13615       format = GST_VIDEO_FORMAT_v308;
13616       break;
13617     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13618       format = GST_VIDEO_FORMAT_v216;
13619       break;
13620     case FOURCC_v210:
13621       format = GST_VIDEO_FORMAT_v210;
13622       break;
13623     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13624       format = GST_VIDEO_FORMAT_r210;
13625       break;
13626       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13627          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13628          format = GST_VIDEO_FORMAT_v410;
13629          break;
13630        */
13631       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13632        * but different order than AYUV
13633        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13634        format = GST_VIDEO_FORMAT_v408;
13635        break;
13636        */
13637     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13638     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13639       _codec ("MPEG-1 video");
13640       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13641           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13642       break;
13643     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13644     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13645     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13646     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13647     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13648     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13649     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13650     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13651     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13652     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13653     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13654     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13655     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13656     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13657     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13658     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13659     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13660     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13661     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13662     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13663     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13664     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13665     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13666     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13667     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13668     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13669     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13670     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13671     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13672     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13673     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13674     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13675     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13676     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13677     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13678     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13679     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13680     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13681     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13682     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13683     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13684     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13685     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13686     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13687     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13688     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13689     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13690       _codec ("MPEG-2 video");
13691       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13692           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13693       break;
13694     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13695       _codec ("GIF still images");
13696       caps = gst_caps_new_empty_simple ("image/gif");
13697       break;
13698     case FOURCC_h263:
13699     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13700     case FOURCC_s263:
13701     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13702       _codec ("H.263");
13703       /* ffmpeg uses the height/width props, don't know why */
13704       caps = gst_caps_new_simple ("video/x-h263",
13705           "variant", G_TYPE_STRING, "itu", NULL);
13706       break;
13707     case FOURCC_mp4v:
13708     case FOURCC_MP4V:
13709       _codec ("MPEG-4 video");
13710       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13711           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13712       break;
13713     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13714     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13715       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13716       caps = gst_caps_new_simple ("video/x-msmpeg",
13717           "msmpegversion", G_TYPE_INT, 43, NULL);
13718       break;
13719     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13720       _codec ("DivX 3");
13721       caps = gst_caps_new_simple ("video/x-divx",
13722           "divxversion", G_TYPE_INT, 3, NULL);
13723       break;
13724     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13725     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13726       _codec ("DivX 4");
13727       caps = gst_caps_new_simple ("video/x-divx",
13728           "divxversion", G_TYPE_INT, 4, NULL);
13729       break;
13730     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13731       _codec ("DivX 5");
13732       caps = gst_caps_new_simple ("video/x-divx",
13733           "divxversion", G_TYPE_INT, 5, NULL);
13734       break;
13735
13736     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13737       _codec ("FFV1");
13738       caps = gst_caps_new_simple ("video/x-ffv",
13739           "ffvversion", G_TYPE_INT, 1, NULL);
13740       break;
13741
13742     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13743     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13744     case FOURCC_XVID:
13745     case FOURCC_xvid:
13746     case FOURCC_FMP4:
13747     case FOURCC_fmp4:
13748     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13749       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13750           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13751       _codec ("MPEG-4");
13752       break;
13753
13754     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13755       _codec ("Cinepak");
13756       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13757       break;
13758     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13759       _codec ("Apple QuickDraw");
13760       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13761       break;
13762     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13763       _codec ("Apple video");
13764       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13765       break;
13766     case FOURCC_H264:
13767     case FOURCC_avc1:
13768       _codec ("H.264 / AVC");
13769       caps = gst_caps_new_simple ("video/x-h264",
13770           "stream-format", G_TYPE_STRING, "avc",
13771           "alignment", G_TYPE_STRING, "au", NULL);
13772       break;
13773     case FOURCC_avc3:
13774       _codec ("H.264 / AVC");
13775       caps = gst_caps_new_simple ("video/x-h264",
13776           "stream-format", G_TYPE_STRING, "avc3",
13777           "alignment", G_TYPE_STRING, "au", NULL);
13778       break;
13779     case FOURCC_H265:
13780     case FOURCC_hvc1:
13781       _codec ("H.265 / HEVC");
13782       caps = gst_caps_new_simple ("video/x-h265",
13783           "stream-format", G_TYPE_STRING, "hvc1",
13784           "alignment", G_TYPE_STRING, "au", NULL);
13785       break;
13786     case FOURCC_hev1:
13787       _codec ("H.265 / HEVC");
13788       caps = gst_caps_new_simple ("video/x-h265",
13789           "stream-format", G_TYPE_STRING, "hev1",
13790           "alignment", G_TYPE_STRING, "au", NULL);
13791       break;
13792     case FOURCC_rle_:
13793       _codec ("Run-length encoding");
13794       caps = gst_caps_new_simple ("video/x-rle",
13795           "layout", G_TYPE_STRING, "quicktime", NULL);
13796       break;
13797     case FOURCC_WRLE:
13798       _codec ("Run-length encoding");
13799       caps = gst_caps_new_simple ("video/x-rle",
13800           "layout", G_TYPE_STRING, "microsoft", NULL);
13801       break;
13802     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13803     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13804       _codec ("Indeo Video 3");
13805       caps = gst_caps_new_simple ("video/x-indeo",
13806           "indeoversion", G_TYPE_INT, 3, NULL);
13807       break;
13808     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13809     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13810       _codec ("Intel Video 4");
13811       caps = gst_caps_new_simple ("video/x-indeo",
13812           "indeoversion", G_TYPE_INT, 4, NULL);
13813       break;
13814     case FOURCC_dvcp:
13815     case FOURCC_dvc_:
13816     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13817     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13818     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13819     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13820     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13821     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13822       _codec ("DV Video");
13823       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13824           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13825       break;
13826     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13827     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13828       _codec ("DVCPro50 Video");
13829       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13830           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13831       break;
13832     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13833     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13834       _codec ("DVCProHD Video");
13835       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13836           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13837       break;
13838     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13839       _codec ("Apple Graphics (SMC)");
13840       caps = gst_caps_new_empty_simple ("video/x-smc");
13841       break;
13842     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13843       _codec ("VP3");
13844       caps = gst_caps_new_empty_simple ("video/x-vp3");
13845       break;
13846     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13847       _codec ("VP6 Flash");
13848       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13849       break;
13850     case FOURCC_XiTh:
13851       _codec ("Theora");
13852       caps = gst_caps_new_empty_simple ("video/x-theora");
13853       /* theora uses one byte of padding in the data stream because it does not
13854        * allow 0 sized packets while theora does */
13855       entry->padding = 1;
13856       break;
13857     case FOURCC_drac:
13858       _codec ("Dirac");
13859       caps = gst_caps_new_empty_simple ("video/x-dirac");
13860       break;
13861     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13862       _codec ("TIFF still images");
13863       caps = gst_caps_new_empty_simple ("image/tiff");
13864       break;
13865     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13866       _codec ("Apple Intermediate Codec");
13867       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13868       break;
13869     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13870       _codec ("AVID DNxHD");
13871       caps = gst_caps_from_string ("video/x-dnxhd");
13872       break;
13873     case FOURCC_VP80:
13874       _codec ("On2 VP8");
13875       caps = gst_caps_from_string ("video/x-vp8");
13876       break;
13877     case FOURCC_apcs:
13878       _codec ("Apple ProRes LT");
13879       caps =
13880           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13881           NULL);
13882       break;
13883     case FOURCC_apch:
13884       _codec ("Apple ProRes HQ");
13885       caps =
13886           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13887           NULL);
13888       break;
13889     case FOURCC_apcn:
13890       _codec ("Apple ProRes");
13891       caps =
13892           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13893           "standard", NULL);
13894       break;
13895     case FOURCC_apco:
13896       _codec ("Apple ProRes Proxy");
13897       caps =
13898           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13899           "proxy", NULL);
13900       break;
13901     case FOURCC_ap4h:
13902       _codec ("Apple ProRes 4444");
13903       caps =
13904           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13905           "4444", NULL);
13906       break;
13907     case FOURCC_ap4x:
13908       _codec ("Apple ProRes 4444 XQ");
13909       caps =
13910           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13911           "4444xq", NULL);
13912       break;
13913     case FOURCC_cfhd:
13914       _codec ("GoPro CineForm");
13915       caps = gst_caps_from_string ("video/x-cineform");
13916       break;
13917     case FOURCC_vc_1:
13918     case FOURCC_ovc1:
13919       _codec ("VC-1");
13920       caps = gst_caps_new_simple ("video/x-wmv",
13921           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13922       break;
13923     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13924     default:
13925     {
13926       caps = _get_unknown_codec_name ("video", fourcc);
13927       break;
13928     }
13929   }
13930
13931   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13932     GstVideoInfo info;
13933
13934     gst_video_info_init (&info);
13935     gst_video_info_set_format (&info, format, entry->width, entry->height);
13936
13937     caps = gst_video_info_to_caps (&info);
13938     *codec_name = gst_pb_utils_get_codec_description (caps);
13939
13940     /* enable clipping for raw video streams */
13941     stream->need_clip = TRUE;
13942     stream->alignment = 32;
13943   }
13944
13945   return caps;
13946 }
13947
13948 static guint
13949 round_up_pow2 (guint n)
13950 {
13951   n = n - 1;
13952   n = n | (n >> 1);
13953   n = n | (n >> 2);
13954   n = n | (n >> 4);
13955   n = n | (n >> 8);
13956   n = n | (n >> 16);
13957   return n + 1;
13958 }
13959
13960 static GstCaps *
13961 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13962     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
13963     int len, gchar ** codec_name)
13964 {
13965   GstCaps *caps;
13966   const GstStructure *s;
13967   const gchar *name;
13968   gint endian = 0;
13969   GstAudioFormat format = 0;
13970   gint depth;
13971
13972   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
13973
13974   depth = entry->bytes_per_packet * 8;
13975
13976   switch (fourcc) {
13977     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
13978     case FOURCC_raw_:
13979       /* 8-bit audio is unsigned */
13980       if (depth == 8)
13981         format = GST_AUDIO_FORMAT_U8;
13982       /* otherwise it's signed and big-endian just like 'twos' */
13983     case FOURCC_twos:
13984       endian = G_BIG_ENDIAN;
13985       /* fall-through */
13986     case FOURCC_sowt:
13987     {
13988       gchar *str;
13989
13990       if (!endian)
13991         endian = G_LITTLE_ENDIAN;
13992
13993       if (!format)
13994         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
13995
13996       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
13997       _codec (str);
13998       g_free (str);
13999
14000       caps = gst_caps_new_simple ("audio/x-raw",
14001           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14002           "layout", G_TYPE_STRING, "interleaved", NULL);
14003       stream->alignment = GST_ROUND_UP_8 (depth);
14004       stream->alignment = round_up_pow2 (stream->alignment);
14005       break;
14006     }
14007     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14008       _codec ("Raw 64-bit floating-point audio");
14009       caps = gst_caps_new_simple ("audio/x-raw",
14010           "format", G_TYPE_STRING, "F64BE",
14011           "layout", G_TYPE_STRING, "interleaved", NULL);
14012       stream->alignment = 8;
14013       break;
14014     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14015       _codec ("Raw 32-bit floating-point audio");
14016       caps = gst_caps_new_simple ("audio/x-raw",
14017           "format", G_TYPE_STRING, "F32BE",
14018           "layout", G_TYPE_STRING, "interleaved", NULL);
14019       stream->alignment = 4;
14020       break;
14021     case FOURCC_in24:
14022       _codec ("Raw 24-bit PCM audio");
14023       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14024        * endian later */
14025       caps = gst_caps_new_simple ("audio/x-raw",
14026           "format", G_TYPE_STRING, "S24BE",
14027           "layout", G_TYPE_STRING, "interleaved", NULL);
14028       stream->alignment = 4;
14029       break;
14030     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14031       _codec ("Raw 32-bit PCM audio");
14032       caps = gst_caps_new_simple ("audio/x-raw",
14033           "format", G_TYPE_STRING, "S32BE",
14034           "layout", G_TYPE_STRING, "interleaved", NULL);
14035       stream->alignment = 4;
14036       break;
14037     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14038       _codec ("Raw 16-bit PCM audio");
14039       caps = gst_caps_new_simple ("audio/x-raw",
14040           "format", G_TYPE_STRING, "S16LE",
14041           "layout", G_TYPE_STRING, "interleaved", NULL);
14042       stream->alignment = 2;
14043       break;
14044     case FOURCC_ulaw:
14045       _codec ("Mu-law audio");
14046       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14047       break;
14048     case FOURCC_alaw:
14049       _codec ("A-law audio");
14050       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14051       break;
14052     case 0x0200736d:
14053     case 0x6d730002:
14054       _codec ("Microsoft ADPCM");
14055       /* Microsoft ADPCM-ACM code 2 */
14056       caps = gst_caps_new_simple ("audio/x-adpcm",
14057           "layout", G_TYPE_STRING, "microsoft", NULL);
14058       break;
14059     case 0x1100736d:
14060     case 0x6d730011:
14061       _codec ("DVI/IMA ADPCM");
14062       caps = gst_caps_new_simple ("audio/x-adpcm",
14063           "layout", G_TYPE_STRING, "dvi", NULL);
14064       break;
14065     case 0x1700736d:
14066     case 0x6d730017:
14067       _codec ("DVI/Intel IMA ADPCM");
14068       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14069       caps = gst_caps_new_simple ("audio/x-adpcm",
14070           "layout", G_TYPE_STRING, "quicktime", NULL);
14071       break;
14072     case 0x5500736d:
14073     case 0x6d730055:
14074       /* MPEG layer 3, CBR only (pre QT4.1) */
14075     case FOURCC__mp3:
14076       _codec ("MPEG-1 layer 3");
14077       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14078       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14079           "mpegversion", G_TYPE_INT, 1, NULL);
14080       break;
14081     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14082       _codec ("MPEG-1 layer 2");
14083       /* MPEG layer 2 */
14084       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14085           "mpegversion", G_TYPE_INT, 1, NULL);
14086       break;
14087     case 0x20736d:
14088     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14089       _codec ("EAC-3 audio");
14090       caps = gst_caps_new_simple ("audio/x-eac3",
14091           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14092       entry->sampled = TRUE;
14093       break;
14094     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14095     case FOURCC_ac_3:
14096       _codec ("AC-3 audio");
14097       caps = gst_caps_new_simple ("audio/x-ac3",
14098           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14099       entry->sampled = TRUE;
14100       break;
14101     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14102     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14103       _codec ("DTS audio");
14104       caps = gst_caps_new_simple ("audio/x-dts",
14105           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14106       entry->sampled = TRUE;
14107       break;
14108     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14109     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14110       _codec ("DTS-HD audio");
14111       caps = gst_caps_new_simple ("audio/x-dts",
14112           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14113       entry->sampled = TRUE;
14114       break;
14115     case FOURCC_MAC3:
14116       _codec ("MACE-3");
14117       caps = gst_caps_new_simple ("audio/x-mace",
14118           "maceversion", G_TYPE_INT, 3, NULL);
14119       break;
14120     case FOURCC_MAC6:
14121       _codec ("MACE-6");
14122       caps = gst_caps_new_simple ("audio/x-mace",
14123           "maceversion", G_TYPE_INT, 6, NULL);
14124       break;
14125     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14126       /* ogg/vorbis */
14127       caps = gst_caps_new_empty_simple ("application/ogg");
14128       break;
14129     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14130       _codec ("DV audio");
14131       caps = gst_caps_new_empty_simple ("audio/x-dv");
14132       break;
14133     case FOURCC_mp4a:
14134       _codec ("MPEG-4 AAC audio");
14135       caps = gst_caps_new_simple ("audio/mpeg",
14136           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14137           "stream-format", G_TYPE_STRING, "raw", NULL);
14138       break;
14139     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14140       _codec ("QDesign Music");
14141       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14142       break;
14143     case FOURCC_QDM2:
14144       _codec ("QDesign Music v.2");
14145       /* FIXME: QDesign music version 2 (no constant) */
14146       if (FALSE && data) {
14147         caps = gst_caps_new_simple ("audio/x-qdm2",
14148             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14149             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14150             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14151       } else {
14152         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14153       }
14154       break;
14155     case FOURCC_agsm:
14156       _codec ("GSM audio");
14157       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14158       break;
14159     case FOURCC_samr:
14160       _codec ("AMR audio");
14161       caps = gst_caps_new_empty_simple ("audio/AMR");
14162       break;
14163     case FOURCC_sawb:
14164       _codec ("AMR-WB audio");
14165       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14166       break;
14167     case FOURCC_ima4:
14168       _codec ("Quicktime IMA ADPCM");
14169       caps = gst_caps_new_simple ("audio/x-adpcm",
14170           "layout", G_TYPE_STRING, "quicktime", NULL);
14171       break;
14172     case FOURCC_alac:
14173       _codec ("Apple lossless audio");
14174       caps = gst_caps_new_empty_simple ("audio/x-alac");
14175       break;
14176     case FOURCC_fLaC:
14177       _codec ("Free Lossless Audio Codec");
14178       caps = gst_caps_new_simple ("audio/x-flac",
14179           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14180       break;
14181     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14182       _codec ("QualComm PureVoice");
14183       caps = gst_caps_from_string ("audio/qcelp");
14184       break;
14185     case FOURCC_wma_:
14186     case FOURCC_owma:
14187       _codec ("WMA");
14188       caps = gst_caps_new_empty_simple ("audio/x-wma");
14189       break;
14190     case FOURCC_opus:
14191       _codec ("Opus");
14192       caps = gst_caps_new_empty_simple ("audio/x-opus");
14193       break;
14194     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14195     {
14196       guint32 flags = 0;
14197       guint32 depth = 0;
14198       guint32 width = 0;
14199       GstAudioFormat format;
14200       enum
14201       {
14202         FLAG_IS_FLOAT = 0x1,
14203         FLAG_IS_BIG_ENDIAN = 0x2,
14204         FLAG_IS_SIGNED = 0x4,
14205         FLAG_IS_PACKED = 0x8,
14206         FLAG_IS_ALIGNED_HIGH = 0x10,
14207         FLAG_IS_NON_INTERLEAVED = 0x20
14208       };
14209       _codec ("Raw LPCM audio");
14210
14211       if (data && len >= 56) {
14212         depth = QT_UINT32 (data + 40);
14213         flags = QT_UINT32 (data + 44);
14214         width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
14215       }
14216       if ((flags & FLAG_IS_FLOAT) == 0) {
14217         if (depth == 0)
14218           depth = 16;
14219         if (width == 0)
14220           width = 16;
14221         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14222             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14223             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14224         caps = gst_caps_new_simple ("audio/x-raw",
14225             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14226             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14227             "non-interleaved" : "interleaved", NULL);
14228         stream->alignment = GST_ROUND_UP_8 (depth);
14229         stream->alignment = round_up_pow2 (stream->alignment);
14230       } else {
14231         if (width == 0)
14232           width = 32;
14233         if (width == 64) {
14234           if (flags & FLAG_IS_BIG_ENDIAN)
14235             format = GST_AUDIO_FORMAT_F64BE;
14236           else
14237             format = GST_AUDIO_FORMAT_F64LE;
14238         } else {
14239           if (flags & FLAG_IS_BIG_ENDIAN)
14240             format = GST_AUDIO_FORMAT_F32BE;
14241           else
14242             format = GST_AUDIO_FORMAT_F32LE;
14243         }
14244         caps = gst_caps_new_simple ("audio/x-raw",
14245             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14246             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14247             "non-interleaved" : "interleaved", NULL);
14248         stream->alignment = width / 8;
14249       }
14250       break;
14251     }
14252     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14253       /* ? */
14254     default:
14255     {
14256       caps = _get_unknown_codec_name ("audio", fourcc);
14257       break;
14258     }
14259   }
14260
14261   if (caps) {
14262     GstCaps *templ_caps =
14263         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14264     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14265     gst_caps_unref (caps);
14266     gst_caps_unref (templ_caps);
14267     caps = intersection;
14268   }
14269
14270   /* enable clipping for raw audio streams */
14271   s = gst_caps_get_structure (caps, 0);
14272   name = gst_structure_get_name (s);
14273   if (g_str_has_prefix (name, "audio/x-raw")) {
14274     stream->need_clip = TRUE;
14275     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14276     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14277   }
14278   return caps;
14279 }
14280
14281 static GstCaps *
14282 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14283     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14284     const guint8 * stsd_entry_data, gchar ** codec_name)
14285 {
14286   GstCaps *caps;
14287
14288   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14289
14290   switch (fourcc) {
14291     case FOURCC_mp4s:
14292       _codec ("DVD subtitle");
14293       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14294       stream->need_process = TRUE;
14295       break;
14296     case FOURCC_text:
14297       _codec ("Quicktime timed text");
14298       goto text;
14299     case FOURCC_tx3g:
14300       _codec ("3GPP timed text");
14301     text:
14302       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14303           "utf8", NULL);
14304       /* actual text piece needs to be extracted */
14305       stream->need_process = TRUE;
14306       break;
14307     case FOURCC_stpp:
14308       _codec ("XML subtitles");
14309       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14310       break;
14311     default:
14312     {
14313       caps = _get_unknown_codec_name ("text", fourcc);
14314       break;
14315     }
14316   }
14317   return caps;
14318 }
14319
14320 static GstCaps *
14321 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14322     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14323     const guint8 * stsd_entry_data, gchar ** codec_name)
14324 {
14325   GstCaps *caps;
14326
14327   switch (fourcc) {
14328     case FOURCC_m1v:
14329       _codec ("MPEG 1 video");
14330       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14331           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14332       break;
14333     default:
14334       caps = NULL;
14335       break;
14336   }
14337   return caps;
14338 }
14339
14340 static void
14341 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14342     const gchar * system_id)
14343 {
14344   gint i;
14345
14346   if (!qtdemux->protection_system_ids)
14347     qtdemux->protection_system_ids =
14348         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14349   /* Check whether we already have an entry for this system ID. */
14350   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14351     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14352     if (g_ascii_strcasecmp (system_id, id) == 0) {
14353       return;
14354     }
14355   }
14356   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14357   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14358           -1));
14359 }