qtdemux: allow larger files
[platform/upstream/gstreamer.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * 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 (200*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_description_index; /* index is 1-based */
418   guint32 def_sample_duration;
419   guint32 def_sample_size;
420   guint32 def_sample_flags;
421
422   gboolean disabled;
423
424   /* stereoscopic video streams */
425   GstVideoMultiviewMode multiview_mode;
426   GstVideoMultiviewFlags multiview_flags;
427
428   /* protected streams */
429   gboolean protected;
430   guint32 protection_scheme_type;
431   guint32 protection_scheme_version;
432   gpointer protection_scheme_info;      /* specific to the protection scheme */
433   GQueue protection_scheme_event_queue;
434 };
435
436 /* Contains properties and cryptographic info for a set of samples from a
437  * track protected using Common Encryption (cenc) */
438 struct _QtDemuxCencSampleSetInfo
439 {
440   GstStructure *default_properties;
441
442   /* @crypto_info holds one GstStructure per sample */
443   GPtrArray *crypto_info;
444 };
445
446 static const gchar *
447 qt_demux_state_string (enum QtDemuxState state)
448 {
449   switch (state) {
450     case QTDEMUX_STATE_INITIAL:
451       return "<INITIAL>";
452     case QTDEMUX_STATE_HEADER:
453       return "<HEADER>";
454     case QTDEMUX_STATE_MOVIE:
455       return "<MOVIE>";
456     case QTDEMUX_STATE_BUFFER_MDAT:
457       return "<BUFFER_MDAT>";
458     default:
459       return "<UNKNOWN>";
460   }
461 }
462
463 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
464 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
465     guint32 fourcc, GstByteReader * parser);
466 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
467 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
468     guint32 fourcc, GstByteReader * parser);
469
470 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
471
472 static GstStaticPadTemplate gst_qtdemux_sink_template =
473     GST_STATIC_PAD_TEMPLATE ("sink",
474     GST_PAD_SINK,
475     GST_PAD_ALWAYS,
476     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
477         "application/x-3gp")
478     );
479
480 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
481 GST_STATIC_PAD_TEMPLATE ("video_%u",
482     GST_PAD_SRC,
483     GST_PAD_SOMETIMES,
484     GST_STATIC_CAPS_ANY);
485
486 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
487 GST_STATIC_PAD_TEMPLATE ("audio_%u",
488     GST_PAD_SRC,
489     GST_PAD_SOMETIMES,
490     GST_STATIC_CAPS_ANY);
491
492 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
493 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
494     GST_PAD_SRC,
495     GST_PAD_SOMETIMES,
496     GST_STATIC_CAPS_ANY);
497
498 #define gst_qtdemux_parent_class parent_class
499 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
500
501 static void gst_qtdemux_dispose (GObject * object);
502
503 static guint32
504 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
505     GstClockTime media_time);
506 static guint32
507 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
508     QtDemuxStream * str, gint64 media_offset);
509
510 #if 0
511 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
512 static GstIndex *gst_qtdemux_get_index (GstElement * element);
513 #endif
514 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
515     GstStateChange transition);
516 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
517 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
518     GstObject * parent, GstPadMode mode, gboolean active);
519
520 static void gst_qtdemux_loop (GstPad * pad);
521 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
522     GstBuffer * inbuf);
523 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
524     GstEvent * event);
525 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
526 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
527     QtDemuxStream * stream);
528 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
529     QtDemuxStream * stream);
530 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
531     gboolean force);
532
533 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
534     const guint8 * buffer, guint length);
535 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
536     const guint8 * buffer, guint length);
537 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
538 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
539     GNode * udta);
540
541 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
542     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
543     GstTagList * list);
544 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
545     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
546     const guint8 * stsd_entry_data, gchar ** codec_name);
547 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
548     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
549     const guint8 * data, int len, gchar ** codec_name);
550 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
551     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
552     gchar ** codec_name);
553 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
554     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
555     const guint8 * stsd_entry_data, gchar ** codec_name);
556
557 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
558     QtDemuxStream * stream, guint32 n);
559 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
560 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
561     QtDemuxStream * stream);
562 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
563     QtDemuxStream * stream);
564 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
565 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
566 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
567     QtDemuxStream * stream);
568 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
569     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
570 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
571     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
572     GstClockTime * _start, GstClockTime * _stop);
573 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
574     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
575
576 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
577 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
578
579 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
580
581 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
582     QtDemuxStream * stream, guint sample_index);
583 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
584     const gchar * id);
585 static void qtdemux_gst_structure_free (GstStructure * gststructure);
586
587 static void
588 gst_qtdemux_class_init (GstQTDemuxClass * klass)
589 {
590   GObjectClass *gobject_class;
591   GstElementClass *gstelement_class;
592
593   gobject_class = (GObjectClass *) klass;
594   gstelement_class = (GstElementClass *) klass;
595
596   parent_class = g_type_class_peek_parent (klass);
597
598   gobject_class->dispose = gst_qtdemux_dispose;
599
600   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
601 #if 0
602   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
603   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
604 #endif
605
606   gst_tag_register_musicbrainz_tags ();
607
608   gst_element_class_add_static_pad_template (gstelement_class,
609       &gst_qtdemux_sink_template);
610   gst_element_class_add_static_pad_template (gstelement_class,
611       &gst_qtdemux_videosrc_template);
612   gst_element_class_add_static_pad_template (gstelement_class,
613       &gst_qtdemux_audiosrc_template);
614   gst_element_class_add_static_pad_template (gstelement_class,
615       &gst_qtdemux_subsrc_template);
616   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
617       "Codec/Demuxer",
618       "Demultiplex a QuickTime file into audio and video streams",
619       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
620
621   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
622
623 }
624
625 static void
626 gst_qtdemux_init (GstQTDemux * qtdemux)
627 {
628   qtdemux->sinkpad =
629       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
630   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
631   gst_pad_set_activatemode_function (qtdemux->sinkpad,
632       qtdemux_sink_activate_mode);
633   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
634   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
635   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
636
637   qtdemux->state = QTDEMUX_STATE_INITIAL;
638   qtdemux->pullbased = FALSE;
639   qtdemux->posted_redirect = FALSE;
640   qtdemux->neededbytes = 16;
641   qtdemux->todrop = 0;
642   qtdemux->adapter = gst_adapter_new ();
643   qtdemux->offset = 0;
644   qtdemux->first_mdat = -1;
645   qtdemux->got_moov = FALSE;
646   qtdemux->mdatoffset = -1;
647   qtdemux->mdatbuffer = NULL;
648   qtdemux->restoredata_buffer = NULL;
649   qtdemux->restoredata_offset = -1;
650   qtdemux->fragment_start = -1;
651   qtdemux->fragment_start_offset = -1;
652   qtdemux->media_caps = NULL;
653   qtdemux->exposed = FALSE;
654   qtdemux->mss_mode = FALSE;
655   qtdemux->pending_newsegment = NULL;
656   qtdemux->upstream_format_is_time = FALSE;
657   qtdemux->have_group_id = FALSE;
658   qtdemux->group_id = G_MAXUINT;
659   qtdemux->cenc_aux_info_offset = 0;
660   qtdemux->cenc_aux_info_sizes = NULL;
661   qtdemux->cenc_aux_sample_count = 0;
662   qtdemux->protection_system_ids = NULL;
663   g_queue_init (&qtdemux->protection_event_queue);
664   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
665   qtdemux->tag_list = gst_tag_list_new_empty ();
666   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
667   qtdemux->flowcombiner = gst_flow_combiner_new ();
668
669   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
670 }
671
672 static void
673 gst_qtdemux_dispose (GObject * object)
674 {
675   GstQTDemux *qtdemux = GST_QTDEMUX (object);
676
677   if (qtdemux->adapter) {
678     g_object_unref (G_OBJECT (qtdemux->adapter));
679     qtdemux->adapter = NULL;
680   }
681   gst_tag_list_unref (qtdemux->tag_list);
682   gst_flow_combiner_free (qtdemux->flowcombiner);
683   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
684       NULL);
685   g_queue_clear (&qtdemux->protection_event_queue);
686
687   g_free (qtdemux->cenc_aux_info_sizes);
688   qtdemux->cenc_aux_info_sizes = NULL;
689
690   G_OBJECT_CLASS (parent_class)->dispose (object);
691 }
692
693 static void
694 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
695 {
696   if (qtdemux->posted_redirect) {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found, a redirect message has been posted"));
700   } else {
701     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
702         (_("This file contains no playable streams.")),
703         ("no known streams found"));
704   }
705 }
706
707 static GstBuffer *
708 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
709 {
710   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
711       mem, size, 0, size, mem, free_func);
712 }
713
714 static GstFlowReturn
715 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
716     GstBuffer ** buf)
717 {
718   GstFlowReturn flow;
719   GstMapInfo map;
720   gsize bsize;
721
722   if (G_UNLIKELY (size == 0)) {
723     GstFlowReturn ret;
724     GstBuffer *tmp = NULL;
725
726     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
727     if (ret != GST_FLOW_OK)
728       return ret;
729
730     gst_buffer_map (tmp, &map, GST_MAP_READ);
731     size = QT_UINT32 (map.data);
732     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
733
734     gst_buffer_unmap (tmp, &map);
735     gst_buffer_unref (tmp);
736   }
737
738   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
739   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
740     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
741       /* we're pulling header but already got most interesting bits,
742        * so never mind the rest (e.g. tags) (that much) */
743       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
744           size);
745       return GST_FLOW_EOS;
746     } else {
747       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
748           (_("This file is invalid and cannot be played.")),
749           ("atom has bogus size %" G_GUINT64_FORMAT, size));
750       return GST_FLOW_ERROR;
751     }
752   }
753
754   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
755
756   if (G_UNLIKELY (flow != GST_FLOW_OK))
757     return flow;
758
759   bsize = gst_buffer_get_size (*buf);
760   /* Catch short reads - we don't want any partial atoms */
761   if (G_UNLIKELY (bsize < size)) {
762     GST_WARNING_OBJECT (qtdemux,
763         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
764     gst_buffer_unref (*buf);
765     *buf = NULL;
766     return GST_FLOW_EOS;
767   }
768
769   return flow;
770 }
771
772 #if 1
773 static gboolean
774 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
775     GstFormat src_format, gint64 src_value, GstFormat dest_format,
776     gint64 * dest_value)
777 {
778   gboolean res = TRUE;
779   QtDemuxStream *stream = gst_pad_get_element_private (pad);
780   gint32 index;
781
782   if (stream->subtype != FOURCC_vide) {
783     res = FALSE;
784     goto done;
785   }
786
787   switch (src_format) {
788     case GST_FORMAT_TIME:
789       switch (dest_format) {
790         case GST_FORMAT_BYTES:{
791           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
792           if (-1 == index) {
793             res = FALSE;
794             goto done;
795           }
796
797           *dest_value = stream->samples[index].offset;
798
799           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
800               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
801               GST_TIME_ARGS (src_value), *dest_value);
802           break;
803         }
804         default:
805           res = FALSE;
806           break;
807       }
808       break;
809     case GST_FORMAT_BYTES:
810       switch (dest_format) {
811         case GST_FORMAT_TIME:{
812           index =
813               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
814               stream, src_value);
815
816           if (-1 == index) {
817             res = FALSE;
818             goto done;
819           }
820
821           *dest_value =
822               QTSTREAMTIME_TO_GSTTIME (stream,
823               stream->samples[index].timestamp);
824           GST_DEBUG_OBJECT (qtdemux,
825               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
826               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
827           break;
828         }
829         default:
830           res = FALSE;
831           break;
832       }
833       break;
834     default:
835       res = FALSE;
836       break;
837   }
838
839 done:
840   return res;
841 }
842 #endif
843
844 static gboolean
845 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
846 {
847   gboolean res = FALSE;
848
849   *duration = GST_CLOCK_TIME_NONE;
850
851   if (qtdemux->duration != 0 &&
852       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
853     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
854     res = TRUE;
855   } else {
856     *duration = GST_CLOCK_TIME_NONE;
857   }
858
859   return res;
860 }
861
862 static gboolean
863 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
864     GstQuery * query)
865 {
866   gboolean res = FALSE;
867   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
868
869   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
870
871   switch (GST_QUERY_TYPE (query)) {
872     case GST_QUERY_POSITION:{
873       GstFormat fmt;
874
875       gst_query_parse_position (query, &fmt, NULL);
876       if (fmt == GST_FORMAT_TIME
877           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
878         gst_query_set_position (query, GST_FORMAT_TIME,
879             qtdemux->segment.position);
880         res = TRUE;
881       }
882     }
883       break;
884     case GST_QUERY_DURATION:{
885       GstFormat fmt;
886
887       gst_query_parse_duration (query, &fmt, NULL);
888       if (fmt == GST_FORMAT_TIME) {
889         /* First try to query upstream */
890         res = gst_pad_query_default (pad, parent, query);
891         if (!res) {
892           GstClockTime duration;
893           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
894             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
895             res = TRUE;
896           }
897         }
898       }
899       break;
900     }
901     case GST_QUERY_CONVERT:{
902       GstFormat src_fmt, dest_fmt;
903       gint64 src_value, dest_value = 0;
904
905       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
906
907       res = gst_qtdemux_src_convert (qtdemux, pad,
908           src_fmt, src_value, dest_fmt, &dest_value);
909       if (res)
910         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
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   gboolean ret;
1631
1632   if (event) {
1633     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1634
1635     gst_event_parse_seek (event, &rate, &format, &flags,
1636         &cur_type, &cur, &stop_type, &stop);
1637     seqnum = gst_event_get_seqnum (event);
1638
1639     /* we have to have a format as the segment format. Try to convert
1640      * if not. */
1641     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1642             stop_type, &stop))
1643       goto no_format;
1644
1645     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1646   } else {
1647     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1648     flags = 0;
1649   }
1650
1651   flush = flags & GST_SEEK_FLAG_FLUSH;
1652
1653   /* stop streaming, either by flushing or by pausing the task */
1654   if (flush) {
1655     flush_event = gst_event_new_flush_start ();
1656     if (seqnum)
1657       gst_event_set_seqnum (flush_event, seqnum);
1658     /* unlock upstream pull_range */
1659     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1660     /* make sure out loop function exits */
1661     gst_qtdemux_push_event (qtdemux, flush_event);
1662   } else {
1663     /* non flushing seek, pause the task */
1664     gst_pad_pause_task (qtdemux->sinkpad);
1665   }
1666
1667   /* wait for streaming to finish */
1668   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1669
1670   /* copy segment, we need this because we still need the old
1671    * segment when we close the current segment. */
1672   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1673
1674   if (event) {
1675     /* configure the segment with the seek variables */
1676     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1677     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1678             cur_type, cur, stop_type, stop, &update)) {
1679       ret = FALSE;
1680       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1681     } else {
1682       /* now do the seek */
1683       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1684     }
1685   } else {
1686     /* now do the seek */
1687     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1688   }
1689
1690   /* prepare for streaming again */
1691   if (flush) {
1692     flush_event = gst_event_new_flush_stop (TRUE);
1693     if (seqnum)
1694       gst_event_set_seqnum (flush_event, seqnum);
1695
1696     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1697     gst_qtdemux_push_event (qtdemux, flush_event);
1698   }
1699
1700   /* commit the new segment */
1701   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1702
1703   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1704     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1705         qtdemux->segment.format, qtdemux->segment.position);
1706     if (seqnum)
1707       gst_message_set_seqnum (msg, seqnum);
1708     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1709   }
1710
1711   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1712   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1713       qtdemux->sinkpad, NULL);
1714
1715   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1716
1717   return ret;
1718
1719   /* ERRORS */
1720 no_format:
1721   {
1722     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1723     return FALSE;
1724   }
1725 }
1726
1727 static gboolean
1728 qtdemux_ensure_index (GstQTDemux * qtdemux)
1729 {
1730   guint i;
1731
1732   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1733
1734   /* Build complete index */
1735   for (i = 0; i < qtdemux->n_streams; i++) {
1736     QtDemuxStream *stream = qtdemux->streams[i];
1737
1738     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1739       goto parse_error;
1740   }
1741   return TRUE;
1742
1743   /* ERRORS */
1744 parse_error:
1745   {
1746     GST_LOG_OBJECT (qtdemux,
1747         "Building complete index of stream %u for seeking failed!", i);
1748     return FALSE;
1749   }
1750 }
1751
1752 static gboolean
1753 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1754     GstEvent * event)
1755 {
1756   gboolean res = TRUE;
1757   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1758
1759   switch (GST_EVENT_TYPE (event)) {
1760     case GST_EVENT_SEEK:
1761     {
1762 #ifndef GST_DISABLE_GST_DEBUG
1763       GstClockTime ts = gst_util_get_timestamp ();
1764 #endif
1765       guint32 seqnum = gst_event_get_seqnum (event);
1766
1767       if (seqnum == qtdemux->segment_seqnum) {
1768         GST_LOG_OBJECT (pad,
1769             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1770         gst_event_unref (event);
1771         return TRUE;
1772       }
1773
1774       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1775         /* seek should be handled by upstream, we might need to re-download fragments */
1776         GST_DEBUG_OBJECT (qtdemux,
1777             "let upstream handle seek for fragmented playback");
1778         goto upstream;
1779       }
1780
1781       /* Build complete index for seeking;
1782        * if not a fragmented file at least */
1783       if (!qtdemux->fragmented)
1784         if (!qtdemux_ensure_index (qtdemux))
1785           goto index_failed;
1786 #ifndef GST_DISABLE_GST_DEBUG
1787       ts = gst_util_get_timestamp () - ts;
1788       GST_INFO_OBJECT (qtdemux,
1789           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1790 #endif
1791     }
1792       if (qtdemux->pullbased) {
1793         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1794       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1795         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1796         res = TRUE;
1797       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1798           && !qtdemux->fragmented) {
1799         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1800       } else {
1801         GST_DEBUG_OBJECT (qtdemux,
1802             "ignoring seek in push mode in current state");
1803         res = FALSE;
1804       }
1805       gst_event_unref (event);
1806       break;
1807     default:
1808     upstream:
1809       res = gst_pad_event_default (pad, parent, event);
1810       break;
1811   }
1812
1813 done:
1814   return res;
1815
1816   /* ERRORS */
1817 index_failed:
1818   {
1819     GST_ERROR_OBJECT (qtdemux, "Index failed");
1820     gst_event_unref (event);
1821     res = FALSE;
1822     goto done;
1823   }
1824 }
1825
1826 /* stream/index return sample that is min/max w.r.t. byte position,
1827  * time is min/max w.r.t. time of samples,
1828  * the latter need not be time of the former sample */
1829 static void
1830 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1831     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1832 {
1833   gint i, n, index;
1834   gint64 time, min_time;
1835   QtDemuxStream *stream;
1836
1837   min_time = -1;
1838   stream = NULL;
1839   index = -1;
1840
1841   for (n = 0; n < qtdemux->n_streams; ++n) {
1842     QtDemuxStream *str;
1843     gint inc;
1844     gboolean set_sample;
1845
1846     str = qtdemux->streams[n];
1847     set_sample = !set;
1848
1849     if (fw) {
1850       i = 0;
1851       inc = 1;
1852     } else {
1853       i = str->n_samples - 1;
1854       inc = -1;
1855     }
1856
1857     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1858       if (str->samples[i].size == 0)
1859         continue;
1860
1861       if (fw && (str->samples[i].offset < byte_pos))
1862         continue;
1863
1864       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1865         continue;
1866
1867       /* move stream to first available sample */
1868       if (set) {
1869         gst_qtdemux_move_stream (qtdemux, str, i);
1870         set_sample = TRUE;
1871       }
1872
1873       /* avoid index from sparse streams since they might be far away */
1874       if (!CUR_STREAM (str)->sparse) {
1875         /* determine min/max time */
1876         time = QTSAMPLE_PTS (str, &str->samples[i]);
1877         if (min_time == -1 || (!fw && time > min_time) ||
1878             (fw && time < min_time)) {
1879           min_time = time;
1880         }
1881
1882         /* determine stream with leading sample, to get its position */
1883         if (!stream ||
1884             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1885             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1886           stream = str;
1887           index = i;
1888         }
1889       }
1890       break;
1891     }
1892
1893     /* no sample for this stream, mark eos */
1894     if (!set_sample)
1895       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1896   }
1897
1898   if (_time)
1899     *_time = min_time;
1900   if (_stream)
1901     *_stream = stream;
1902   if (_index)
1903     *_index = index;
1904 }
1905
1906 static QtDemuxStream *
1907 _create_stream (void)
1908 {
1909   QtDemuxStream *stream;
1910
1911   stream = g_new0 (QtDemuxStream, 1);
1912   /* new streams always need a discont */
1913   stream->discont = TRUE;
1914   /* we enable clipping for raw audio/video streams */
1915   stream->need_clip = FALSE;
1916   stream->need_process = FALSE;
1917   stream->segment_index = -1;
1918   stream->time_position = 0;
1919   stream->sample_index = -1;
1920   stream->offset_in_sample = 0;
1921   stream->new_stream = TRUE;
1922   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1923   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1924   stream->protected = FALSE;
1925   stream->protection_scheme_type = 0;
1926   stream->protection_scheme_version = 0;
1927   stream->protection_scheme_info = NULL;
1928   stream->n_samples_moof = 0;
1929   stream->duration_moof = 0;
1930   stream->duration_last_moof = 0;
1931   stream->alignment = 1;
1932   stream->stream_tags = gst_tag_list_new_empty ();
1933   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1934   g_queue_init (&stream->protection_scheme_event_queue);
1935   return stream;
1936 }
1937
1938 static gboolean
1939 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1940 {
1941   GstStructure *structure;
1942   const gchar *variant;
1943   const GstCaps *mediacaps = NULL;
1944
1945   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1946
1947   structure = gst_caps_get_structure (caps, 0);
1948   variant = gst_structure_get_string (structure, "variant");
1949
1950   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1951     QtDemuxStream *stream;
1952     const GValue *value;
1953
1954     demux->fragmented = TRUE;
1955     demux->mss_mode = TRUE;
1956
1957     if (demux->n_streams > 1) {
1958       /* can't do this, we can only renegotiate for another mss format */
1959       return FALSE;
1960     }
1961
1962     value = gst_structure_get_value (structure, "media-caps");
1963     /* create stream */
1964     if (value) {
1965       const GValue *timescale_v;
1966
1967       /* TODO update when stream changes during playback */
1968
1969       if (demux->n_streams == 0) {
1970         stream = _create_stream ();
1971         demux->streams[demux->n_streams] = stream;
1972         demux->n_streams = 1;
1973         /* mss has no stsd/stsd entry, use id 0 as default */
1974         stream->stsd_entries_length = 1;
1975         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1976         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1977       } else {
1978         stream = demux->streams[0];
1979       }
1980
1981       timescale_v = gst_structure_get_value (structure, "timescale");
1982       if (timescale_v) {
1983         stream->timescale = g_value_get_uint64 (timescale_v);
1984       } else {
1985         /* default mss timescale */
1986         stream->timescale = 10000000;
1987       }
1988       demux->timescale = stream->timescale;
1989
1990       mediacaps = gst_value_get_caps (value);
1991       if (!CUR_STREAM (stream)->caps
1992           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1993         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1994             mediacaps);
1995         stream->new_caps = TRUE;
1996       }
1997       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1998       structure = gst_caps_get_structure (mediacaps, 0);
1999       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2000         stream->subtype = FOURCC_vide;
2001
2002         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2003         gst_structure_get_int (structure, "height",
2004             &CUR_STREAM (stream)->height);
2005         gst_structure_get_fraction (structure, "framerate",
2006             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2007       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2008         gint rate = 0;
2009         stream->subtype = FOURCC_soun;
2010         gst_structure_get_int (structure, "channels",
2011             &CUR_STREAM (stream)->n_channels);
2012         gst_structure_get_int (structure, "rate", &rate);
2013         CUR_STREAM (stream)->rate = rate;
2014       }
2015     }
2016     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2017   } else {
2018     demux->mss_mode = FALSE;
2019   }
2020
2021   return TRUE;
2022 }
2023
2024 static void
2025 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2026 {
2027   gint n;
2028
2029   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2030   gst_pad_stop_task (qtdemux->sinkpad);
2031
2032   if (hard || qtdemux->upstream_format_is_time) {
2033     qtdemux->state = QTDEMUX_STATE_INITIAL;
2034     qtdemux->neededbytes = 16;
2035     qtdemux->todrop = 0;
2036     qtdemux->pullbased = FALSE;
2037     qtdemux->posted_redirect = FALSE;
2038     qtdemux->first_mdat = -1;
2039     qtdemux->header_size = 0;
2040     qtdemux->mdatoffset = -1;
2041     qtdemux->restoredata_offset = -1;
2042     if (qtdemux->mdatbuffer)
2043       gst_buffer_unref (qtdemux->mdatbuffer);
2044     if (qtdemux->restoredata_buffer)
2045       gst_buffer_unref (qtdemux->restoredata_buffer);
2046     qtdemux->mdatbuffer = NULL;
2047     qtdemux->restoredata_buffer = NULL;
2048     qtdemux->mdatleft = 0;
2049     qtdemux->mdatsize = 0;
2050     if (qtdemux->comp_brands)
2051       gst_buffer_unref (qtdemux->comp_brands);
2052     qtdemux->comp_brands = NULL;
2053     qtdemux->last_moov_offset = -1;
2054     if (qtdemux->moov_node_compressed) {
2055       g_node_destroy (qtdemux->moov_node_compressed);
2056       if (qtdemux->moov_node)
2057         g_free (qtdemux->moov_node->data);
2058     }
2059     qtdemux->moov_node_compressed = NULL;
2060     if (qtdemux->moov_node)
2061       g_node_destroy (qtdemux->moov_node);
2062     qtdemux->moov_node = NULL;
2063     if (qtdemux->tag_list)
2064       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2065     qtdemux->tag_list = gst_tag_list_new_empty ();
2066     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2067 #if 0
2068     if (qtdemux->element_index)
2069       gst_object_unref (qtdemux->element_index);
2070     qtdemux->element_index = NULL;
2071 #endif
2072     qtdemux->major_brand = 0;
2073     if (qtdemux->pending_newsegment)
2074       gst_event_unref (qtdemux->pending_newsegment);
2075     qtdemux->pending_newsegment = NULL;
2076     qtdemux->upstream_format_is_time = FALSE;
2077     qtdemux->upstream_seekable = FALSE;
2078     qtdemux->upstream_size = 0;
2079
2080     qtdemux->fragment_start = -1;
2081     qtdemux->fragment_start_offset = -1;
2082     qtdemux->duration = 0;
2083     qtdemux->moof_offset = 0;
2084     qtdemux->chapters_track_id = 0;
2085     qtdemux->have_group_id = FALSE;
2086     qtdemux->group_id = G_MAXUINT;
2087
2088     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2089         NULL);
2090     g_queue_clear (&qtdemux->protection_event_queue);
2091   }
2092   qtdemux->offset = 0;
2093   gst_adapter_clear (qtdemux->adapter);
2094   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2095   qtdemux->segment_seqnum = 0;
2096
2097   if (hard) {
2098     for (n = 0; n < qtdemux->n_streams; n++) {
2099       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2100       qtdemux->streams[n] = NULL;
2101     }
2102     qtdemux->n_streams = 0;
2103     qtdemux->n_video_streams = 0;
2104     qtdemux->n_audio_streams = 0;
2105     qtdemux->n_sub_streams = 0;
2106     qtdemux->exposed = FALSE;
2107     qtdemux->fragmented = FALSE;
2108     qtdemux->mss_mode = FALSE;
2109     gst_caps_replace (&qtdemux->media_caps, NULL);
2110     qtdemux->timescale = 0;
2111     qtdemux->got_moov = FALSE;
2112     if (qtdemux->protection_system_ids) {
2113       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2114       qtdemux->protection_system_ids = NULL;
2115     }
2116   } else if (qtdemux->mss_mode) {
2117     gst_flow_combiner_reset (qtdemux->flowcombiner);
2118     for (n = 0; n < qtdemux->n_streams; n++)
2119       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2120   } else {
2121     gst_flow_combiner_reset (qtdemux->flowcombiner);
2122     for (n = 0; n < qtdemux->n_streams; n++) {
2123       qtdemux->streams[n]->sent_eos = FALSE;
2124       qtdemux->streams[n]->time_position = 0;
2125       qtdemux->streams[n]->accumulated_base = 0;
2126     }
2127     if (!qtdemux->pending_newsegment) {
2128       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2129       if (qtdemux->segment_seqnum)
2130         gst_event_set_seqnum (qtdemux->pending_newsegment,
2131             qtdemux->segment_seqnum);
2132     }
2133   }
2134 }
2135
2136
2137 /* Maps the @segment to the qt edts internal segments and pushes
2138  * the correspnding segment event.
2139  *
2140  * If it ends up being at a empty segment, a gap will be pushed and the next
2141  * edts segment will be activated in sequence.
2142  *
2143  * To be used in push-mode only */
2144 static void
2145 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2146 {
2147   gint n, i;
2148
2149   for (n = 0; n < qtdemux->n_streams; n++) {
2150     QtDemuxStream *stream = qtdemux->streams[n];
2151
2152     stream->time_position = segment->start;
2153
2154     /* in push mode we should be guaranteed that we will have empty segments
2155      * at the beginning and then one segment after, other scenarios are not
2156      * supported and are discarded when parsing the edts */
2157     for (i = 0; i < stream->n_segments; i++) {
2158       if (stream->segments[i].stop_time > segment->start) {
2159         gst_qtdemux_activate_segment (qtdemux, stream, i,
2160             stream->time_position);
2161         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2162           /* push the empty segment and move to the next one */
2163           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2164               stream->time_position);
2165           continue;
2166         }
2167
2168         g_assert (i == stream->n_segments - 1);
2169       }
2170     }
2171   }
2172 }
2173
2174 static gboolean
2175 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2176     GstEvent * event)
2177 {
2178   GstQTDemux *demux = GST_QTDEMUX (parent);
2179   gboolean res = TRUE;
2180
2181   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2182
2183   switch (GST_EVENT_TYPE (event)) {
2184     case GST_EVENT_SEGMENT:
2185     {
2186       gint64 offset = 0;
2187       QtDemuxStream *stream;
2188       gint idx;
2189       GstSegment segment;
2190
2191       /* some debug output */
2192       gst_event_copy_segment (event, &segment);
2193       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2194           &segment);
2195
2196       /* erase any previously set segment */
2197       gst_event_replace (&demux->pending_newsegment, NULL);
2198
2199       if (segment.format == GST_FORMAT_TIME) {
2200         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2201         gst_event_replace (&demux->pending_newsegment, event);
2202         demux->upstream_format_is_time = TRUE;
2203       } else {
2204         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2205             "not in time format");
2206
2207         /* chain will send initial newsegment after pads have been added */
2208         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2209           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2210           goto exit;
2211         }
2212       }
2213
2214       /* check if this matches a time seek we received previously
2215        * FIXME for backwards compatibility reasons we use the
2216        * seek_offset here to compare. In the future we might want to
2217        * change this to use the seqnum as it uniquely should identify
2218        * the segment that corresponds to the seek. */
2219       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2220           ", received segment offset %" G_GINT64_FORMAT,
2221           demux->seek_offset, segment.start);
2222       if (segment.format == GST_FORMAT_BYTES
2223           && demux->seek_offset == segment.start) {
2224         GST_OBJECT_LOCK (demux);
2225         offset = segment.start;
2226
2227         segment.format = GST_FORMAT_TIME;
2228         segment.start = demux->push_seek_start;
2229         segment.stop = demux->push_seek_stop;
2230         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2231             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2232             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2233         GST_OBJECT_UNLOCK (demux);
2234       }
2235
2236       /* we only expect a BYTE segment, e.g. following a seek */
2237       if (segment.format == GST_FORMAT_BYTES) {
2238         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2239           offset = segment.start;
2240
2241           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2242               NULL, (gint64 *) & segment.start);
2243           if ((gint64) segment.start < 0)
2244             segment.start = 0;
2245         }
2246         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2247           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2248               NULL, (gint64 *) & segment.stop);
2249           /* keyframe seeking should already arrange for start >= stop,
2250            * but make sure in other rare cases */
2251           segment.stop = MAX (segment.stop, segment.start);
2252         }
2253       } else if (segment.format == GST_FORMAT_TIME) {
2254         /* push all data on the adapter before starting this
2255          * new segment */
2256         gst_qtdemux_process_adapter (demux, TRUE);
2257       } else {
2258         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2259         goto exit;
2260       }
2261
2262       /* We shouldn't modify upstream driven TIME FORMAT segment */
2263       if (!demux->upstream_format_is_time) {
2264         /* accept upstream's notion of segment and distribute along */
2265         segment.format = GST_FORMAT_TIME;
2266         segment.position = segment.time = segment.start;
2267         segment.duration = demux->segment.duration;
2268         segment.base = gst_segment_to_running_time (&demux->segment,
2269             GST_FORMAT_TIME, demux->segment.position);
2270       }
2271
2272       gst_segment_copy_into (&segment, &demux->segment);
2273       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2274
2275       /* map segment to internal qt segments and push on each stream */
2276       if (demux->n_streams) {
2277         if (demux->fragmented) {
2278           GstEvent *segment_event = gst_event_new_segment (&segment);
2279
2280           gst_event_replace (&demux->pending_newsegment, NULL);
2281           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2282           gst_qtdemux_push_event (demux, segment_event);
2283         } else {
2284           gst_event_replace (&demux->pending_newsegment, NULL);
2285           gst_qtdemux_map_and_push_segments (demux, &segment);
2286         }
2287       }
2288
2289       /* clear leftover in current segment, if any */
2290       gst_adapter_clear (demux->adapter);
2291
2292       /* set up streaming thread */
2293       demux->offset = offset;
2294       if (demux->upstream_format_is_time) {
2295         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2296             "set values to restart reading from a new atom");
2297         demux->neededbytes = 16;
2298         demux->todrop = 0;
2299       } else {
2300         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2301             NULL);
2302         if (stream) {
2303           demux->todrop = stream->samples[idx].offset - offset;
2304           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2305         } else {
2306           /* set up for EOS */
2307           demux->neededbytes = -1;
2308           demux->todrop = 0;
2309         }
2310       }
2311     exit:
2312       gst_event_unref (event);
2313       res = TRUE;
2314       goto drop;
2315     }
2316     case GST_EVENT_FLUSH_START:
2317     {
2318       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2319         gst_event_unref (event);
2320         goto drop;
2321       }
2322       break;
2323     }
2324     case GST_EVENT_FLUSH_STOP:
2325     {
2326       guint64 dur;
2327
2328       dur = demux->segment.duration;
2329       gst_qtdemux_reset (demux, FALSE);
2330       demux->segment.duration = dur;
2331
2332       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2333         gst_event_unref (event);
2334         goto drop;
2335       }
2336       break;
2337     }
2338     case GST_EVENT_EOS:
2339       /* If we are in push mode, and get an EOS before we've seen any streams,
2340        * then error out - we have nowhere to send the EOS */
2341       if (!demux->pullbased) {
2342         gint i;
2343         gboolean has_valid_stream = FALSE;
2344         for (i = 0; i < demux->n_streams; i++) {
2345           if (demux->streams[i]->pad != NULL) {
2346             has_valid_stream = TRUE;
2347             break;
2348           }
2349         }
2350         if (!has_valid_stream)
2351           gst_qtdemux_post_no_playable_stream_error (demux);
2352         else {
2353           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2354               (guint) gst_adapter_available (demux->adapter));
2355           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2356             res = FALSE;
2357           }
2358         }
2359       }
2360       break;
2361     case GST_EVENT_CAPS:{
2362       GstCaps *caps = NULL;
2363
2364       gst_event_parse_caps (event, &caps);
2365       gst_qtdemux_setcaps (demux, caps);
2366       res = TRUE;
2367       gst_event_unref (event);
2368       goto drop;
2369     }
2370     case GST_EVENT_PROTECTION:
2371     {
2372       const gchar *system_id = NULL;
2373
2374       gst_event_parse_protection (event, &system_id, NULL, NULL);
2375       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2376           system_id);
2377       gst_qtdemux_append_protection_system_id (demux, system_id);
2378       /* save the event for later, for source pads that have not been created */
2379       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2380       /* send it to all pads that already exist */
2381       gst_qtdemux_push_event (demux, event);
2382       res = TRUE;
2383       goto drop;
2384     }
2385     default:
2386       break;
2387   }
2388
2389   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2390
2391 drop:
2392   return res;
2393 }
2394
2395 #if 0
2396 static void
2397 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2398 {
2399   GstQTDemux *demux = GST_QTDEMUX (element);
2400
2401   GST_OBJECT_LOCK (demux);
2402   if (demux->element_index)
2403     gst_object_unref (demux->element_index);
2404   if (index) {
2405     demux->element_index = gst_object_ref (index);
2406   } else {
2407     demux->element_index = NULL;
2408   }
2409   GST_OBJECT_UNLOCK (demux);
2410   /* object lock might be taken again */
2411   if (index)
2412     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2413   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2414       demux->element_index, demux->index_id);
2415 }
2416
2417 static GstIndex *
2418 gst_qtdemux_get_index (GstElement * element)
2419 {
2420   GstIndex *result = NULL;
2421   GstQTDemux *demux = GST_QTDEMUX (element);
2422
2423   GST_OBJECT_LOCK (demux);
2424   if (demux->element_index)
2425     result = gst_object_ref (demux->element_index);
2426   GST_OBJECT_UNLOCK (demux);
2427
2428   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2429
2430   return result;
2431 }
2432 #endif
2433
2434 static void
2435 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2436 {
2437   g_free ((gpointer) stream->stco.data);
2438   stream->stco.data = NULL;
2439   g_free ((gpointer) stream->stsz.data);
2440   stream->stsz.data = NULL;
2441   g_free ((gpointer) stream->stsc.data);
2442   stream->stsc.data = NULL;
2443   g_free ((gpointer) stream->stts.data);
2444   stream->stts.data = NULL;
2445   g_free ((gpointer) stream->stss.data);
2446   stream->stss.data = NULL;
2447   g_free ((gpointer) stream->stps.data);
2448   stream->stps.data = NULL;
2449   g_free ((gpointer) stream->ctts.data);
2450   stream->ctts.data = NULL;
2451 }
2452
2453 static void
2454 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2455     QtDemuxStream * stream)
2456 {
2457   g_free (stream->segments);
2458   stream->segments = NULL;
2459   stream->segment_index = -1;
2460   stream->accumulated_base = 0;
2461 }
2462
2463 static void
2464 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2465     QtDemuxStream * stream)
2466 {
2467   g_free (stream->samples);
2468   stream->samples = NULL;
2469   gst_qtdemux_stbl_free (stream);
2470
2471   /* fragments */
2472   g_free (stream->ra_entries);
2473   stream->ra_entries = NULL;
2474   stream->n_ra_entries = 0;
2475
2476   stream->sample_index = -1;
2477   stream->stbl_index = -1;
2478   stream->n_samples = 0;
2479   stream->time_position = 0;
2480
2481   stream->n_samples_moof = 0;
2482   stream->duration_moof = 0;
2483   stream->duration_last_moof = 0;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2488 {
2489   gint i;
2490   if (stream->allocator)
2491     gst_object_unref (stream->allocator);
2492   while (stream->buffers) {
2493     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2494     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2495   }
2496   for (i = 0; i < stream->stsd_entries_length; i++) {
2497     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2498     if (entry->rgb8_palette) {
2499       gst_memory_unref (entry->rgb8_palette);
2500       entry->rgb8_palette = NULL;
2501     }
2502     entry->sparse = FALSE;
2503   }
2504
2505   gst_tag_list_unref (stream->stream_tags);
2506   stream->stream_tags = gst_tag_list_new_empty ();
2507   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2508   g_free (stream->redirect_uri);
2509   stream->redirect_uri = NULL;
2510   stream->sent_eos = FALSE;
2511   stream->protected = FALSE;
2512   if (stream->protection_scheme_info) {
2513     if (stream->protection_scheme_type == FOURCC_cenc) {
2514       QtDemuxCencSampleSetInfo *info =
2515           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2516       if (info->default_properties)
2517         gst_structure_free (info->default_properties);
2518       if (info->crypto_info)
2519         g_ptr_array_free (info->crypto_info, TRUE);
2520     }
2521     g_free (stream->protection_scheme_info);
2522     stream->protection_scheme_info = NULL;
2523   }
2524   stream->protection_scheme_type = 0;
2525   stream->protection_scheme_version = 0;
2526   g_queue_foreach (&stream->protection_scheme_event_queue,
2527       (GFunc) gst_event_unref, NULL);
2528   g_queue_clear (&stream->protection_scheme_event_queue);
2529   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2530   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2531 }
2532
2533 static void
2534 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2535 {
2536   gint i;
2537   gst_qtdemux_stream_clear (qtdemux, stream);
2538   for (i = 0; i < stream->stsd_entries_length; i++) {
2539     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2540     if (entry->caps) {
2541       gst_caps_unref (entry->caps);
2542       entry->caps = NULL;
2543     }
2544   }
2545   gst_tag_list_unref (stream->stream_tags);
2546   if (stream->pad) {
2547     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2548     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2549   }
2550   g_free (stream->stsd_entries);
2551   g_free (stream);
2552 }
2553
2554 static void
2555 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2556 {
2557   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2558
2559   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2560   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2561   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2562   qtdemux->n_streams--;
2563 }
2564
2565 static GstStateChangeReturn
2566 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2567 {
2568   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2569   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2570
2571   switch (transition) {
2572     case GST_STATE_CHANGE_PAUSED_TO_READY:
2573       break;
2574     default:
2575       break;
2576   }
2577
2578   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2579
2580   switch (transition) {
2581     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2582       gst_qtdemux_reset (qtdemux, TRUE);
2583       break;
2584     }
2585     default:
2586       break;
2587   }
2588
2589   return result;
2590 }
2591
2592 static void
2593 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2594 {
2595   /* counts as header data */
2596   qtdemux->header_size += length;
2597
2598   /* only consider at least a sufficiently complete ftyp atom */
2599   if (length >= 20) {
2600     GstBuffer *buf;
2601
2602     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2603     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2604         GST_FOURCC_ARGS (qtdemux->major_brand));
2605     if (qtdemux->comp_brands)
2606       gst_buffer_unref (qtdemux->comp_brands);
2607     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2608     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2609   }
2610 }
2611
2612 static void
2613 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2614     GstTagList * xmptaglist)
2615 {
2616   /* Strip out bogus fields */
2617   if (xmptaglist) {
2618     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2619       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2620       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2621     } else {
2622       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2623     }
2624
2625     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2626
2627     /* prioritize native tags using _KEEP mode */
2628     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2629     gst_tag_list_unref (xmptaglist);
2630   }
2631 }
2632
2633 static void
2634 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2635     guint offset)
2636 {
2637   GstByteReader br;
2638   guint8 version;
2639   guint32 flags = 0;
2640   guint i;
2641   guint8 iv_size = 8;
2642   QtDemuxStream *stream;
2643   GstStructure *structure;
2644   QtDemuxCencSampleSetInfo *ss_info = NULL;
2645   const gchar *system_id;
2646   gboolean uses_sub_sample_encryption = FALSE;
2647
2648   if (qtdemux->n_streams == 0)
2649     return;
2650
2651   stream = qtdemux->streams[0];
2652
2653   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2654   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2655     GST_WARNING_OBJECT (qtdemux,
2656         "Attempting PIFF box parsing on an unencrypted stream.");
2657     return;
2658   }
2659
2660   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2661       G_TYPE_STRING, &system_id, NULL);
2662   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2663
2664   stream->protected = TRUE;
2665   stream->protection_scheme_type = FOURCC_cenc;
2666
2667   if (!stream->protection_scheme_info)
2668     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2669
2670   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2671
2672   if (ss_info->default_properties)
2673     gst_structure_free (ss_info->default_properties);
2674
2675   ss_info->default_properties =
2676       gst_structure_new ("application/x-cenc",
2677       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2678
2679   if (ss_info->crypto_info) {
2680     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2681     g_ptr_array_free (ss_info->crypto_info, TRUE);
2682     ss_info->crypto_info = NULL;
2683   }
2684
2685   /* skip UUID */
2686   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2687
2688   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2689     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2690     return;
2691   }
2692
2693   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2694     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2695     return;
2696   }
2697
2698   if ((flags & 0x000001)) {
2699     guint32 algorithm_id = 0;
2700     const guint8 *kid;
2701     GstBuffer *kid_buf;
2702     gboolean is_encrypted = TRUE;
2703
2704     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2705       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2706       return;
2707     }
2708
2709     algorithm_id >>= 8;
2710     if (algorithm_id == 0) {
2711       is_encrypted = FALSE;
2712     } else if (algorithm_id == 1) {
2713       /* FIXME: maybe store this in properties? */
2714       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2715     } else if (algorithm_id == 2) {
2716       /* FIXME: maybe store this in properties? */
2717       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2718     }
2719
2720     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2721       return;
2722
2723     if (!gst_byte_reader_get_data (&br, 16, &kid))
2724       return;
2725
2726     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2727     gst_buffer_fill (kid_buf, 0, kid, 16);
2728     if (ss_info->default_properties)
2729       gst_structure_free (ss_info->default_properties);
2730     ss_info->default_properties =
2731         gst_structure_new ("application/x-cenc",
2732         "iv_size", G_TYPE_UINT, iv_size,
2733         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2734         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2735     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2736         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2737     gst_buffer_unref (kid_buf);
2738   } else if ((flags & 0x000002)) {
2739     uses_sub_sample_encryption = TRUE;
2740   }
2741
2742   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2743     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2744     return;
2745   }
2746
2747   ss_info->crypto_info =
2748       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2749       (GDestroyNotify) qtdemux_gst_structure_free);
2750
2751   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2752     GstStructure *properties;
2753     guint8 *data;
2754     GstBuffer *buf;
2755
2756     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2757     if (properties == NULL) {
2758       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2759       return;
2760     }
2761
2762     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2763       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2764       gst_structure_free (properties);
2765       return;
2766     }
2767     buf = gst_buffer_new_wrapped (data, iv_size);
2768     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2769     gst_buffer_unref (buf);
2770
2771     if (uses_sub_sample_encryption) {
2772       guint16 n_subsamples;
2773
2774       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2775           || n_subsamples == 0) {
2776         GST_ERROR_OBJECT (qtdemux,
2777             "failed to get subsample count for sample %u", i);
2778         gst_structure_free (properties);
2779         return;
2780       }
2781       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2782       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2783         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2784             i);
2785         gst_structure_free (properties);
2786         return;
2787       }
2788       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2789       gst_structure_set (properties,
2790           "subsample_count", G_TYPE_UINT, n_subsamples,
2791           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2792       gst_buffer_unref (buf);
2793     } else {
2794       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2795     }
2796
2797     g_ptr_array_add (ss_info->crypto_info, properties);
2798   }
2799 }
2800
2801 static void
2802 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2803 {
2804   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2805     0x97, 0xA9, 0x42, 0xE8,
2806     0x9C, 0x71, 0x99, 0x94,
2807     0x91, 0xE3, 0xAF, 0xAC
2808   };
2809   static const guint8 playready_uuid[] = {
2810     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2811     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2812   };
2813
2814   static const guint8 piff_sample_encryption_uuid[] = {
2815     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2816     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2817   };
2818
2819   guint offset;
2820
2821   /* counts as header data */
2822   qtdemux->header_size += length;
2823
2824   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2825
2826   if (length <= offset + 16) {
2827     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2828     return;
2829   }
2830
2831   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2832     GstBuffer *buf;
2833     GstTagList *taglist;
2834
2835     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2836         length - offset - 16, NULL);
2837     taglist = gst_tag_list_from_xmp_buffer (buf);
2838     gst_buffer_unref (buf);
2839
2840     /* make sure we have a usable taglist */
2841     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2842
2843     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2844
2845   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2846     int len;
2847     const gunichar2 *s_utf16;
2848     char *contents;
2849
2850     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2851     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2852     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2853     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2854
2855     g_free (contents);
2856
2857     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2858         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2859         (NULL));
2860   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2861     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2862   } else {
2863     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2864         GST_READ_UINT32_LE (buffer + offset),
2865         GST_READ_UINT32_LE (buffer + offset + 4),
2866         GST_READ_UINT32_LE (buffer + offset + 8),
2867         GST_READ_UINT32_LE (buffer + offset + 12));
2868   }
2869 }
2870
2871 static void
2872 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2873 {
2874   GstSidxParser sidx_parser;
2875   GstIsoffParserResult res;
2876   guint consumed;
2877
2878   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2879
2880   res =
2881       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2882       &consumed);
2883   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2884   if (res == GST_ISOFF_QT_PARSER_DONE) {
2885     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2886   }
2887   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2888 }
2889
2890 /* caller verifies at least 8 bytes in buf */
2891 static void
2892 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2893     guint64 * plength, guint32 * pfourcc)
2894 {
2895   guint64 length;
2896   guint32 fourcc;
2897
2898   length = QT_UINT32 (data);
2899   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2900   fourcc = QT_FOURCC (data + 4);
2901   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2902
2903   if (length == 0) {
2904     length = G_MAXUINT64;
2905   } else if (length == 1 && size >= 16) {
2906     /* this means we have an extended size, which is the 64 bit value of
2907      * the next 8 bytes */
2908     length = QT_UINT64 (data + 8);
2909     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2910   }
2911
2912   if (plength)
2913     *plength = length;
2914   if (pfourcc)
2915     *pfourcc = fourcc;
2916 }
2917
2918 static gboolean
2919 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2920 {
2921   guint32 version = 0;
2922   GstClockTime duration = 0;
2923
2924   if (!gst_byte_reader_get_uint32_be (br, &version))
2925     goto failed;
2926
2927   version >>= 24;
2928   if (version == 1) {
2929     if (!gst_byte_reader_get_uint64_be (br, &duration))
2930       goto failed;
2931   } else {
2932     guint32 dur = 0;
2933
2934     if (!gst_byte_reader_get_uint32_be (br, &dur))
2935       goto failed;
2936     duration = dur;
2937   }
2938
2939   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2940   qtdemux->duration = duration;
2941
2942   return TRUE;
2943
2944 failed:
2945   {
2946     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2947     return FALSE;
2948   }
2949 }
2950
2951 static gboolean
2952 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2953     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2954 {
2955   if (!stream->parsed_trex && qtdemux->moov_node) {
2956     GNode *mvex, *trex;
2957     GstByteReader trex_data;
2958
2959     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2960     if (mvex) {
2961       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2962           &trex_data);
2963       while (trex) {
2964         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2965
2966         /* skip version/flags */
2967         if (!gst_byte_reader_skip (&trex_data, 4))
2968           goto next;
2969         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2970           goto next;
2971         if (id != stream->track_id)
2972           goto next;
2973         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2974           goto next;
2975         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2976           goto next;
2977         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2978           goto next;
2979         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2980           goto next;
2981
2982         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2983             "duration %d,  size %d, flags 0x%x", stream->track_id,
2984             dur, size, flags);
2985
2986         stream->parsed_trex = TRUE;
2987         stream->def_sample_description_index = sdi;
2988         stream->def_sample_duration = dur;
2989         stream->def_sample_size = size;
2990         stream->def_sample_flags = flags;
2991
2992       next:
2993         /* iterate all siblings */
2994         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2995             &trex_data);
2996       }
2997     }
2998   }
2999
3000   *ds_duration = stream->def_sample_duration;
3001   *ds_size = stream->def_sample_size;
3002   *ds_flags = stream->def_sample_flags;
3003
3004   /* even then, above values are better than random ... */
3005   if (G_UNLIKELY (!stream->parsed_trex)) {
3006     GST_WARNING_OBJECT (qtdemux,
3007         "failed to find fragment defaults for stream %d", stream->track_id);
3008     return FALSE;
3009   }
3010
3011   return TRUE;
3012 }
3013
3014 /* This method should be called whenever a more accurate duration might
3015  * have been found. It will update all relevant variables if/where needed
3016  */
3017 static void
3018 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3019 {
3020   guint i;
3021   guint64 movdur;
3022   GstClockTime prevdur;
3023
3024   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3025
3026   if (movdur > qtdemux->duration) {
3027     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3028     GST_DEBUG_OBJECT (qtdemux,
3029         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3030         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3031     qtdemux->duration = movdur;
3032     GST_DEBUG_OBJECT (qtdemux,
3033         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3034         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3035         GST_TIME_ARGS (qtdemux->segment.stop));
3036     if (qtdemux->segment.duration == prevdur) {
3037       /* If the current segment has duration/stop identical to previous duration
3038        * update them also (because they were set at that point in time with
3039        * the wrong duration */
3040       /* We convert the value *from* the timescale version to avoid rounding errors */
3041       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3042       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3043       qtdemux->segment.duration = fixeddur;
3044       qtdemux->segment.stop = fixeddur;
3045     }
3046   }
3047   for (i = 0; i < qtdemux->n_streams; i++) {
3048     QtDemuxStream *stream = qtdemux->streams[i];
3049     if (stream) {
3050       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3051       if (movdur > stream->duration) {
3052         GST_DEBUG_OBJECT (qtdemux,
3053             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3054             GST_TIME_ARGS (duration));
3055         stream->duration = movdur;
3056         /* internal duration tracking state has been updated above, so */
3057         /* preserve an open-ended dummy segment rather than repeatedly updating
3058          * it and spamming downstream accordingly with segment events */
3059         if (stream->dummy_segment &&
3060             GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3061           /* Update all dummy values to new duration */
3062           stream->segments[0].stop_time = duration;
3063           stream->segments[0].duration = duration;
3064           stream->segments[0].media_stop = duration;
3065
3066           /* let downstream know we possibly have a new stop time */
3067           if (stream->segment_index != -1) {
3068             GstClockTime pos;
3069
3070             if (qtdemux->segment.rate >= 0) {
3071               pos = stream->segment.start;
3072             } else {
3073               pos = stream->segment.stop;
3074             }
3075
3076             gst_qtdemux_stream_update_segment (qtdemux, stream,
3077                 stream->segment_index, pos, NULL, NULL);
3078           }
3079         }
3080       }
3081     }
3082   }
3083 }
3084
3085 static gboolean
3086 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3087     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3088     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3089     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3090     gboolean has_tfdt)
3091 {
3092   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3093   guint64 timestamp;
3094   gint32 data_offset = 0;
3095   guint32 flags = 0, first_flags = 0, samples_count = 0;
3096   gint i;
3097   guint8 *data;
3098   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3099   QtDemuxSample *sample;
3100   gboolean ismv = FALSE;
3101   gint64 initial_offset;
3102
3103   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3104       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3105       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3106       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3107
3108   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3109     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3110     return TRUE;
3111   }
3112
3113   /* presence of stss or not can't really tell us much,
3114    * and flags and so on tend to be marginally reliable in these files */
3115   if (stream->subtype == FOURCC_soun) {
3116     GST_DEBUG_OBJECT (qtdemux,
3117         "sound track in fragmented file; marking all keyframes");
3118     stream->all_keyframe = TRUE;
3119   }
3120
3121   if (!gst_byte_reader_skip (trun, 1) ||
3122       !gst_byte_reader_get_uint24_be (trun, &flags))
3123     goto fail;
3124
3125   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3126     goto fail;
3127
3128   if (flags & TR_DATA_OFFSET) {
3129     /* note this is really signed */
3130     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3131       goto fail;
3132     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3133     /* default base offset = first byte of moof */
3134     if (*base_offset == -1) {
3135       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3136       *base_offset = moof_offset;
3137     }
3138     *running_offset = *base_offset + data_offset;
3139   } else {
3140     /* if no offset at all, that would mean data starts at moof start,
3141      * which is a bit wrong and is ismv crappy way, so compensate
3142      * assuming data is in mdat following moof */
3143     if (*base_offset == -1) {
3144       *base_offset = moof_offset + moof_length + 8;
3145       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3146       ismv = TRUE;
3147     }
3148     if (*running_offset == -1)
3149       *running_offset = *base_offset;
3150   }
3151
3152   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3153       *running_offset);
3154   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3155       data_offset, flags, samples_count);
3156
3157   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3158     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3159       GST_DEBUG_OBJECT (qtdemux,
3160           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3161       flags ^= TR_FIRST_SAMPLE_FLAGS;
3162     } else {
3163       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3164         goto fail;
3165       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3166     }
3167   }
3168
3169   /* FIXME ? spec says other bits should also be checked to determine
3170    * entry size (and prefix size for that matter) */
3171   entry_size = 0;
3172   dur_offset = size_offset = 0;
3173   if (flags & TR_SAMPLE_DURATION) {
3174     GST_LOG_OBJECT (qtdemux, "entry duration present");
3175     dur_offset = entry_size;
3176     entry_size += 4;
3177   }
3178   if (flags & TR_SAMPLE_SIZE) {
3179     GST_LOG_OBJECT (qtdemux, "entry size present");
3180     size_offset = entry_size;
3181     entry_size += 4;
3182   }
3183   if (flags & TR_SAMPLE_FLAGS) {
3184     GST_LOG_OBJECT (qtdemux, "entry flags present");
3185     flags_offset = entry_size;
3186     entry_size += 4;
3187   }
3188   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3189     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3190     ct_offset = entry_size;
3191     entry_size += 4;
3192   }
3193
3194   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3195     goto fail;
3196   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3197
3198   if (stream->n_samples + samples_count >=
3199       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3200     goto index_too_big;
3201
3202   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3203       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3204       (stream->n_samples + samples_count) *
3205       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3206
3207   /* create a new array of samples if it's the first sample parsed */
3208   if (stream->n_samples == 0) {
3209     g_assert (stream->samples == NULL);
3210     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3211     /* or try to reallocate it with space enough to insert the new samples */
3212   } else
3213     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3214         stream->n_samples + samples_count);
3215   if (stream->samples == NULL)
3216     goto out_of_memory;
3217
3218   if (qtdemux->fragment_start != -1) {
3219     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3220     qtdemux->fragment_start = -1;
3221   } else {
3222     if (stream->n_samples == 0) {
3223       if (decode_ts > 0) {
3224         timestamp = decode_ts;
3225       } else if (stream->pending_seek != NULL) {
3226         /* if we don't have a timestamp from a tfdt box, we'll use the one
3227          * from the mfra seek table */
3228         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3229             GST_TIME_ARGS (stream->pending_seek->ts));
3230
3231         /* FIXME: this is not fully correct, the timestamp refers to the random
3232          * access sample refered to in the tfra entry, which may not necessarily
3233          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3234         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3235       } else {
3236         timestamp = 0;
3237       }
3238
3239       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3240       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3241           GST_TIME_ARGS (gst_ts));
3242     } else {
3243       /* subsequent fragments extend stream */
3244       timestamp =
3245           stream->samples[stream->n_samples - 1].timestamp +
3246           stream->samples[stream->n_samples - 1].duration;
3247
3248       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3249        * difference (1 sec.) between decode_ts and timestamp, prefer the
3250        * former */
3251       if (has_tfdt && !qtdemux->upstream_format_is_time
3252           && ABSDIFF (decode_ts, timestamp) >
3253           MAX (stream->duration_last_moof / 2,
3254               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3255         GST_INFO_OBJECT (qtdemux,
3256             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3257             ") are significantly different (more than %" GST_TIME_FORMAT
3258             "), using decode_ts",
3259             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3260             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3261             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3262                     MAX (stream->duration_last_moof / 2,
3263                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3264         timestamp = decode_ts;
3265       }
3266
3267       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3268       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3269           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3270     }
3271   }
3272
3273   initial_offset = *running_offset;
3274
3275   sample = stream->samples + stream->n_samples;
3276   for (i = 0; i < samples_count; i++) {
3277     guint32 dur, size, sflags, ct;
3278
3279     /* first read sample data */
3280     if (flags & TR_SAMPLE_DURATION) {
3281       dur = QT_UINT32 (data + dur_offset);
3282     } else {
3283       dur = d_sample_duration;
3284     }
3285     if (flags & TR_SAMPLE_SIZE) {
3286       size = QT_UINT32 (data + size_offset);
3287     } else {
3288       size = d_sample_size;
3289     }
3290     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3291       if (i == 0) {
3292         sflags = first_flags;
3293       } else {
3294         sflags = d_sample_flags;
3295       }
3296     } else if (flags & TR_SAMPLE_FLAGS) {
3297       sflags = QT_UINT32 (data + flags_offset);
3298     } else {
3299       sflags = d_sample_flags;
3300     }
3301     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3302       ct = QT_UINT32 (data + ct_offset);
3303     } else {
3304       ct = 0;
3305     }
3306     data += entry_size;
3307
3308     /* fill the sample information */
3309     sample->offset = *running_offset;
3310     sample->pts_offset = ct;
3311     sample->size = size;
3312     sample->timestamp = timestamp;
3313     sample->duration = dur;
3314     /* sample-is-difference-sample */
3315     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3316      * now idea how it relates to bitfield other than massive LE/BE confusion */
3317     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3318     *running_offset += size;
3319     timestamp += dur;
3320     stream->duration_moof += dur;
3321     sample++;
3322   }
3323
3324   /* Update total duration if needed */
3325   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3326
3327   /* Pre-emptively figure out size of mdat based on trun information.
3328    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3329    * size, else we will still be able to use this when dealing with gap'ed
3330    * input */
3331   qtdemux->mdatleft = *running_offset - initial_offset;
3332   qtdemux->mdatoffset = initial_offset;
3333   qtdemux->mdatsize = qtdemux->mdatleft;
3334
3335   stream->n_samples += samples_count;
3336   stream->n_samples_moof += samples_count;
3337
3338   if (stream->pending_seek != NULL)
3339     stream->pending_seek = NULL;
3340
3341   return TRUE;
3342
3343 fail:
3344   {
3345     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3346     return FALSE;
3347   }
3348 out_of_memory:
3349   {
3350     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3351         stream->n_samples);
3352     return FALSE;
3353   }
3354 index_too_big:
3355   {
3356     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3357         "be larger than %uMB (broken file?)", stream->n_samples,
3358         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3359     return FALSE;
3360   }
3361 }
3362
3363 /* find stream with @id */
3364 static inline QtDemuxStream *
3365 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3366 {
3367   QtDemuxStream *stream;
3368   gint i;
3369
3370   /* check */
3371   if (G_UNLIKELY (!id)) {
3372     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3373     return NULL;
3374   }
3375
3376   /* try to get it fast and simple */
3377   if (G_LIKELY (id <= qtdemux->n_streams)) {
3378     stream = qtdemux->streams[id - 1];
3379     if (G_LIKELY (stream->track_id == id))
3380       return stream;
3381   }
3382
3383   /* linear search otherwise */
3384   for (i = 0; i < qtdemux->n_streams; i++) {
3385     stream = qtdemux->streams[i];
3386     if (stream->track_id == id)
3387       return stream;
3388   }
3389   if (qtdemux->mss_mode) {
3390     /* mss should have only 1 stream anyway */
3391     return qtdemux->streams[0];
3392   }
3393
3394   return NULL;
3395 }
3396
3397 static gboolean
3398 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3399     guint32 * fragment_number)
3400 {
3401   if (!gst_byte_reader_skip (mfhd, 4))
3402     goto fail;
3403   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3404     goto fail;
3405   return TRUE;
3406 fail:
3407   {
3408     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3409     return FALSE;
3410   }
3411 }
3412
3413 static gboolean
3414 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3415     QtDemuxStream ** stream, guint32 * default_sample_duration,
3416     guint32 * default_sample_size, guint32 * default_sample_flags,
3417     gint64 * base_offset)
3418 {
3419   guint32 flags = 0;
3420   guint32 track_id = 0;
3421
3422   if (!gst_byte_reader_skip (tfhd, 1) ||
3423       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3424     goto invalid_track;
3425
3426   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3427     goto invalid_track;
3428
3429   *stream = qtdemux_find_stream (qtdemux, track_id);
3430   if (G_UNLIKELY (!*stream))
3431     goto unknown_stream;
3432
3433   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3434     *base_offset = qtdemux->moof_offset;
3435
3436   if (flags & TF_BASE_DATA_OFFSET)
3437     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3438       goto invalid_track;
3439
3440   /* obtain stream defaults */
3441   qtdemux_parse_trex (qtdemux, *stream,
3442       default_sample_duration, default_sample_size, default_sample_flags);
3443
3444   (*stream)->stsd_sample_description_id =
3445       (*stream)->def_sample_description_index - 1;
3446
3447   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3448     guint32 sample_description_index;
3449     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3450       goto invalid_track;
3451     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3452   }
3453
3454   if (qtdemux->mss_mode) {
3455     /* mss has no stsd entry */
3456     (*stream)->stsd_sample_description_id = 0;
3457   }
3458
3459   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3460     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3461       goto invalid_track;
3462
3463   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3464     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3465       goto invalid_track;
3466
3467   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3468     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3469       goto invalid_track;
3470
3471   return TRUE;
3472
3473 invalid_track:
3474   {
3475     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3476     return FALSE;
3477   }
3478 unknown_stream:
3479   {
3480     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3481     return TRUE;
3482   }
3483 }
3484
3485 static gboolean
3486 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3487     guint64 * decode_time)
3488 {
3489   guint32 version = 0;
3490
3491   if (!gst_byte_reader_get_uint32_be (br, &version))
3492     return FALSE;
3493
3494   version >>= 24;
3495   if (version == 1) {
3496     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3497       goto failed;
3498   } else {
3499     guint32 dec_time = 0;
3500     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3501       goto failed;
3502     *decode_time = dec_time;
3503   }
3504
3505   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3506       *decode_time);
3507
3508   return TRUE;
3509
3510 failed:
3511   {
3512     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3513     return FALSE;
3514   }
3515 }
3516
3517 /* Returns a pointer to a GstStructure containing the properties of
3518  * the stream sample identified by @sample_index. The caller must unref
3519  * the returned object after use. Returns NULL if unsuccessful. */
3520 static GstStructure *
3521 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3522     QtDemuxStream * stream, guint sample_index)
3523 {
3524   QtDemuxCencSampleSetInfo *info = NULL;
3525
3526   g_return_val_if_fail (stream != NULL, NULL);
3527   g_return_val_if_fail (stream->protected, NULL);
3528   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3529
3530   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3531
3532   /* Currently, cenc properties for groups of samples are not supported, so
3533    * simply return a copy of the default sample properties */
3534   return gst_structure_copy (info->default_properties);
3535 }
3536
3537 /* Parses the sizes of sample auxiliary information contained within a stream,
3538  * as given in a saiz box. Returns array of sample_count guint8 size values,
3539  * or NULL on failure */
3540 static guint8 *
3541 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3542     GstByteReader * br, guint32 * sample_count)
3543 {
3544   guint32 flags = 0;
3545   guint8 *info_sizes;
3546   guint8 default_info_size;
3547
3548   g_return_val_if_fail (qtdemux != NULL, NULL);
3549   g_return_val_if_fail (stream != NULL, NULL);
3550   g_return_val_if_fail (br != NULL, NULL);
3551   g_return_val_if_fail (sample_count != NULL, NULL);
3552
3553   if (!gst_byte_reader_get_uint32_be (br, &flags))
3554     return NULL;
3555
3556   if (flags & 0x1) {
3557     /* aux_info_type and aux_info_type_parameter are ignored */
3558     if (!gst_byte_reader_skip (br, 8))
3559       return NULL;
3560   }
3561
3562   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3563     return NULL;
3564   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3565
3566   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3567     return NULL;
3568   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3569
3570
3571   if (default_info_size == 0) {
3572     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3573       return NULL;
3574     }
3575   } else {
3576     info_sizes = g_new (guint8, *sample_count);
3577     memset (info_sizes, default_info_size, *sample_count);
3578   }
3579
3580   return info_sizes;
3581 }
3582
3583 /* Parses the offset of sample auxiliary information contained within a stream,
3584  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3585 static gboolean
3586 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3587     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3588     guint64 * offset)
3589 {
3590   guint8 version = 0;
3591   guint32 flags = 0;
3592   guint32 aux_info_type = 0;
3593   guint32 aux_info_type_parameter = 0;
3594   guint32 entry_count;
3595   guint32 off_32;
3596   guint64 off_64;
3597   const guint8 *aux_info_type_data = NULL;
3598
3599   g_return_val_if_fail (qtdemux != NULL, FALSE);
3600   g_return_val_if_fail (stream != NULL, FALSE);
3601   g_return_val_if_fail (br != NULL, FALSE);
3602   g_return_val_if_fail (offset != NULL, FALSE);
3603
3604   if (!gst_byte_reader_get_uint8 (br, &version))
3605     return FALSE;
3606
3607   if (!gst_byte_reader_get_uint24_be (br, &flags))
3608     return FALSE;
3609
3610   if (flags & 0x1) {
3611
3612     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3613       return FALSE;
3614     aux_info_type = QT_FOURCC (aux_info_type_data);
3615
3616     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3617       return FALSE;
3618   } else if (stream->protected) {
3619     aux_info_type = stream->protection_scheme_type;
3620   } else {
3621     aux_info_type = CUR_STREAM (stream)->fourcc;
3622   }
3623
3624   if (info_type)
3625     *info_type = aux_info_type;
3626   if (info_type_parameter)
3627     *info_type_parameter = aux_info_type_parameter;
3628
3629   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3630       "aux_info_type_parameter:  %#06x",
3631       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3632
3633   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3634     return FALSE;
3635
3636   if (entry_count != 1) {
3637     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3638     return FALSE;
3639   }
3640
3641   if (version == 0) {
3642     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3643       return FALSE;
3644     *offset = (guint64) off_32;
3645   } else {
3646     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3647       return FALSE;
3648     *offset = off_64;
3649   }
3650
3651   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3652   return TRUE;
3653 }
3654
3655 static void
3656 qtdemux_gst_structure_free (GstStructure * gststructure)
3657 {
3658   if (gststructure) {
3659     gst_structure_free (gststructure);
3660   }
3661 }
3662
3663 /* Parses auxiliary information relating to samples protected using Common
3664  * Encryption (cenc); the format of this information is defined in
3665  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3666 static gboolean
3667 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3668     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3669 {
3670   QtDemuxCencSampleSetInfo *ss_info = NULL;
3671   guint8 size;
3672   gint i;
3673   GPtrArray *old_crypto_info = NULL;
3674   guint old_entries = 0;
3675
3676   g_return_val_if_fail (qtdemux != NULL, FALSE);
3677   g_return_val_if_fail (stream != NULL, FALSE);
3678   g_return_val_if_fail (br != NULL, FALSE);
3679   g_return_val_if_fail (stream->protected, FALSE);
3680   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3681
3682   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3683
3684   if (ss_info->crypto_info) {
3685     old_crypto_info = ss_info->crypto_info;
3686     /* Count number of non-null entries remaining at the tail end */
3687     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3688       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3689         break;
3690       old_entries++;
3691     }
3692   }
3693
3694   ss_info->crypto_info =
3695       g_ptr_array_new_full (sample_count + old_entries,
3696       (GDestroyNotify) qtdemux_gst_structure_free);
3697
3698   /* We preserve old entries because we parse the next moof in advance
3699    * of consuming all samples from the previous moof, and otherwise
3700    * we'd discard the corresponding crypto info for the samples
3701    * from the previous fragment. */
3702   if (old_entries) {
3703     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3704         old_entries);
3705     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3706       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3707               i));
3708       g_ptr_array_index (old_crypto_info, i) = NULL;
3709     }
3710   }
3711
3712   if (old_crypto_info) {
3713     /* Everything now belongs to the new array */
3714     g_ptr_array_free (old_crypto_info, TRUE);
3715   }
3716
3717   for (i = 0; i < sample_count; ++i) {
3718     GstStructure *properties;
3719     guint16 n_subsamples = 0;
3720     guint8 *data;
3721     guint iv_size;
3722     GstBuffer *buf;
3723
3724     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3725     if (properties == NULL) {
3726       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3727       return FALSE;
3728     }
3729     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3730       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3731       gst_structure_free (properties);
3732       return FALSE;
3733     }
3734     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3735       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3736       gst_structure_free (properties);
3737       return FALSE;
3738     }
3739     buf = gst_buffer_new_wrapped (data, iv_size);
3740     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3741     gst_buffer_unref (buf);
3742     size = info_sizes[i];
3743     if (size > iv_size) {
3744       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3745           || !(n_subsamples > 0)) {
3746         gst_structure_free (properties);
3747         GST_ERROR_OBJECT (qtdemux,
3748             "failed to get subsample count for sample %u", i);
3749         return FALSE;
3750       }
3751       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3752       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3753         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3754             i);
3755         gst_structure_free (properties);
3756         return FALSE;
3757       }
3758       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3759       if (!buf) {
3760         gst_structure_free (properties);
3761         return FALSE;
3762       }
3763       gst_structure_set (properties,
3764           "subsample_count", G_TYPE_UINT, n_subsamples,
3765           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3766       gst_buffer_unref (buf);
3767     } else {
3768       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3769     }
3770     g_ptr_array_add (ss_info->crypto_info, properties);
3771   }
3772   return TRUE;
3773 }
3774
3775 /* Converts a UUID in raw byte form to a string representation, as defined in
3776  * RFC 4122. The caller takes ownership of the returned string and is
3777  * responsible for freeing it after use. */
3778 static gchar *
3779 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3780 {
3781   const guint8 *uuid = (const guint8 *) uuid_bytes;
3782
3783   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3784       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3785       uuid[0], uuid[1], uuid[2], uuid[3],
3786       uuid[4], uuid[5], uuid[6], uuid[7],
3787       uuid[8], uuid[9], uuid[10], uuid[11],
3788       uuid[12], uuid[13], uuid[14], uuid[15]);
3789 }
3790
3791 /* Parses a Protection System Specific Header box (pssh), as defined in the
3792  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3793  * information needed by a specific content protection system in order to
3794  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3795  * otherwise. */
3796 static gboolean
3797 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3798 {
3799   gchar *sysid_string;
3800   guint32 pssh_size = QT_UINT32 (node->data);
3801   GstBuffer *pssh = NULL;
3802   GstEvent *event = NULL;
3803   guint32 parent_box_type;
3804   gint i;
3805
3806   if (G_UNLIKELY (pssh_size < 32U)) {
3807     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3808     return FALSE;
3809   }
3810
3811   sysid_string =
3812       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3813
3814   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3815
3816   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3817   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3818       gst_buffer_get_size (pssh));
3819
3820   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3821
3822   /* Push an event containing the pssh box onto the queues of all streams. */
3823   event = gst_event_new_protection (sysid_string, pssh,
3824       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3825   for (i = 0; i < qtdemux->n_streams; ++i) {
3826     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3827         gst_event_ref (event));
3828   }
3829   g_free (sysid_string);
3830   gst_event_unref (event);
3831   gst_buffer_unref (pssh);
3832   return TRUE;
3833 }
3834
3835 static gboolean
3836 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3837     guint64 moof_offset, QtDemuxStream * stream)
3838 {
3839   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3840   GNode *uuid_node;
3841   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3842   GNode *saiz_node, *saio_node, *pssh_node;
3843   GstByteReader saiz_data, saio_data;
3844   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3845   gint64 base_offset, running_offset;
3846   guint32 frag_num;
3847
3848   /* NOTE @stream ignored */
3849
3850   moof_node = g_node_new ((guint8 *) buffer);
3851   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3852   qtdemux_node_dump (qtdemux, moof_node);
3853
3854   /* Get fragment number from mfhd and check it's valid */
3855   mfhd_node =
3856       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3857   if (mfhd_node == NULL)
3858     goto missing_mfhd;
3859   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3860     goto fail;
3861   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3862
3863   /* unknown base_offset to start with */
3864   base_offset = running_offset = -1;
3865   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3866   while (traf_node) {
3867     guint64 decode_time = 0;
3868
3869     /* Fragment Header node */
3870     tfhd_node =
3871         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3872         &tfhd_data);
3873     if (!tfhd_node)
3874       goto missing_tfhd;
3875     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3876             &ds_size, &ds_flags, &base_offset))
3877       goto missing_tfhd;
3878
3879     /* The following code assumes at most a single set of sample auxiliary
3880      * data in the fragment (consisting of a saiz box and a corresponding saio
3881      * box); in theory, however, there could be multiple sets of sample
3882      * auxiliary data in a fragment. */
3883     saiz_node =
3884         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3885         &saiz_data);
3886     if (saiz_node) {
3887       guint32 info_type = 0;
3888       guint64 offset = 0;
3889       guint32 info_type_parameter = 0;
3890
3891       g_free (qtdemux->cenc_aux_info_sizes);
3892
3893       qtdemux->cenc_aux_info_sizes =
3894           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3895           &qtdemux->cenc_aux_sample_count);
3896       if (qtdemux->cenc_aux_info_sizes == NULL) {
3897         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3898         goto fail;
3899       }
3900       saio_node =
3901           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3902           &saio_data);
3903       if (!saio_node) {
3904         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3905         g_free (qtdemux->cenc_aux_info_sizes);
3906         qtdemux->cenc_aux_info_sizes = NULL;
3907         goto fail;
3908       }
3909
3910       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3911                   &info_type, &info_type_parameter, &offset))) {
3912         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3913         g_free (qtdemux->cenc_aux_info_sizes);
3914         qtdemux->cenc_aux_info_sizes = NULL;
3915         goto fail;
3916       }
3917       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3918         offset += (guint64) (base_offset - qtdemux->moof_offset);
3919       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3920         GstByteReader br;
3921         if (offset > length) {
3922           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3923           qtdemux->cenc_aux_info_offset = offset;
3924         } else {
3925           gst_byte_reader_init (&br, buffer + offset, length - offset);
3926           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3927                   qtdemux->cenc_aux_info_sizes,
3928                   qtdemux->cenc_aux_sample_count)) {
3929             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3930             g_free (qtdemux->cenc_aux_info_sizes);
3931             qtdemux->cenc_aux_info_sizes = NULL;
3932             goto fail;
3933           }
3934         }
3935       }
3936     }
3937
3938     tfdt_node =
3939         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3940         &tfdt_data);
3941     if (tfdt_node) {
3942       /* We'll use decode_time to interpolate timestamps
3943        * in case the input timestamps are missing */
3944       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3945
3946       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3947           " (%" GST_TIME_FORMAT ")", decode_time,
3948           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3949                   decode_time) : GST_CLOCK_TIME_NONE));
3950
3951       /* Discard the fragment buffer timestamp info to avoid using it.
3952        * Rely on tfdt instead as it is more accurate than the timestamp
3953        * that is fetched from a manifest/playlist and is usually
3954        * less accurate. */
3955       qtdemux->fragment_start = -1;
3956     }
3957
3958     if (G_UNLIKELY (!stream)) {
3959       /* we lost track of offset, we'll need to regain it,
3960        * but can delay complaining until later or avoid doing so altogether */
3961       base_offset = -2;
3962       goto next;
3963     }
3964     if (G_UNLIKELY (base_offset < -1))
3965       goto lost_offset;
3966
3967     if (qtdemux->upstream_format_is_time)
3968       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3969
3970     /* initialise moof sample data */
3971     stream->n_samples_moof = 0;
3972     stream->duration_last_moof = stream->duration_moof;
3973     stream->duration_moof = 0;
3974
3975     /* Track Run node */
3976     trun_node =
3977         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3978         &trun_data);
3979     while (trun_node) {
3980       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3981           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3982           &running_offset, decode_time, (tfdt_node != NULL));
3983       /* iterate all siblings */
3984       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3985           &trun_data);
3986     }
3987
3988     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3989     if (uuid_node) {
3990       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3991       guint32 box_length = QT_UINT32 (uuid_buffer);
3992
3993       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3994     }
3995
3996     /* if no new base_offset provided for next traf,
3997      * base is end of current traf */
3998     base_offset = running_offset;
3999     running_offset = -1;
4000
4001     if (stream->n_samples_moof && stream->duration_moof)
4002       stream->new_caps = TRUE;
4003
4004   next:
4005     /* iterate all siblings */
4006     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4007   }
4008
4009   /* parse any protection system info */
4010   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4011   while (pssh_node) {
4012     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4013     qtdemux_parse_pssh (qtdemux, pssh_node);
4014     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4015   }
4016
4017   g_node_destroy (moof_node);
4018   return TRUE;
4019
4020 missing_tfhd:
4021   {
4022     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4023     goto fail;
4024   }
4025 missing_mfhd:
4026   {
4027     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4028     goto fail;
4029   }
4030 lost_offset:
4031   {
4032     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4033     goto fail;
4034   }
4035 fail:
4036   {
4037     g_node_destroy (moof_node);
4038     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4039         (_("This file is corrupt and cannot be played.")), (NULL));
4040     return FALSE;
4041   }
4042 }
4043
4044 #if 0
4045 /* might be used if some day we actually use mfra & co
4046  * for random access to fragments,
4047  * but that will require quite some modifications and much less relying
4048  * on a sample array */
4049 #endif
4050
4051 static gboolean
4052 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4053 {
4054   QtDemuxStream *stream;
4055   guint32 ver_flags, track_id, len, num_entries, i;
4056   guint value_size, traf_size, trun_size, sample_size;
4057   guint64 time = 0, moof_offset = 0;
4058 #if 0
4059   GstBuffer *buf = NULL;
4060   GstFlowReturn ret;
4061 #endif
4062   GstByteReader tfra;
4063
4064   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4065
4066   if (!gst_byte_reader_skip (&tfra, 8))
4067     return FALSE;
4068
4069   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4070     return FALSE;
4071
4072   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4073       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4074       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4075     return FALSE;
4076
4077   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4078
4079   stream = qtdemux_find_stream (qtdemux, track_id);
4080   if (stream == NULL)
4081     goto unknown_trackid;
4082
4083   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4084   sample_size = (len & 3) + 1;
4085   trun_size = ((len & 12) >> 2) + 1;
4086   traf_size = ((len & 48) >> 4) + 1;
4087
4088   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4089       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4090
4091   if (num_entries == 0)
4092     goto no_samples;
4093
4094   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4095           value_size + value_size + traf_size + trun_size + sample_size))
4096     goto corrupt_file;
4097
4098   g_free (stream->ra_entries);
4099   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4100   stream->n_ra_entries = num_entries;
4101
4102   for (i = 0; i < num_entries; i++) {
4103     qt_atom_parser_get_offset (&tfra, value_size, &time);
4104     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4105     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4106     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4107     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4108
4109     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4110
4111     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4112         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4113
4114     stream->ra_entries[i].ts = time;
4115     stream->ra_entries[i].moof_offset = moof_offset;
4116
4117     /* don't want to go through the entire file and read all moofs at startup */
4118 #if 0
4119     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4120     if (ret != GST_FLOW_OK)
4121       goto corrupt_file;
4122     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4123         moof_offset, stream);
4124     gst_buffer_unref (buf);
4125 #endif
4126   }
4127
4128   check_update_duration (qtdemux, time);
4129
4130   return TRUE;
4131
4132 /* ERRORS */
4133 unknown_trackid:
4134   {
4135     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4136     return FALSE;
4137   }
4138 corrupt_file:
4139   {
4140     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4141     return FALSE;
4142   }
4143 no_samples:
4144   {
4145     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4146     return FALSE;
4147   }
4148 }
4149
4150 static gboolean
4151 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4152 {
4153   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4154   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4155   GstBuffer *mfro = NULL, *mfra = NULL;
4156   GstFlowReturn flow;
4157   gboolean ret = FALSE;
4158   GNode *mfra_node, *tfra_node;
4159   guint64 mfra_offset = 0;
4160   guint32 fourcc, mfra_size;
4161   gint64 len;
4162
4163   /* query upstream size in bytes */
4164   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4165     goto size_query_failed;
4166
4167   /* mfro box should be at the very end of the file */
4168   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4169   if (flow != GST_FLOW_OK)
4170     goto exit;
4171
4172   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4173
4174   fourcc = QT_FOURCC (mfro_map.data + 4);
4175   if (fourcc != FOURCC_mfro)
4176     goto exit;
4177
4178   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4179   if (mfro_map.size < 16)
4180     goto invalid_mfro_size;
4181
4182   mfra_size = QT_UINT32 (mfro_map.data + 12);
4183   if (mfra_size >= len)
4184     goto invalid_mfra_size;
4185
4186   mfra_offset = len - mfra_size;
4187
4188   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4189       mfra_offset, mfra_size);
4190
4191   /* now get and parse mfra box */
4192   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4193   if (flow != GST_FLOW_OK)
4194     goto broken_file;
4195
4196   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4197
4198   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4199   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4200
4201   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4202
4203   while (tfra_node) {
4204     qtdemux_parse_tfra (qtdemux, tfra_node);
4205     /* iterate all siblings */
4206     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4207   }
4208   g_node_destroy (mfra_node);
4209
4210   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4211   ret = TRUE;
4212
4213 exit:
4214
4215   if (mfro) {
4216     if (mfro_map.memory != NULL)
4217       gst_buffer_unmap (mfro, &mfro_map);
4218     gst_buffer_unref (mfro);
4219   }
4220   if (mfra) {
4221     if (mfra_map.memory != NULL)
4222       gst_buffer_unmap (mfra, &mfra_map);
4223     gst_buffer_unref (mfra);
4224   }
4225   return ret;
4226
4227 /* ERRORS */
4228 size_query_failed:
4229   {
4230     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4231     goto exit;
4232   }
4233 invalid_mfro_size:
4234   {
4235     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4236     goto exit;
4237   }
4238 invalid_mfra_size:
4239   {
4240     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4241     goto exit;
4242   }
4243 broken_file:
4244   {
4245     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4246     goto exit;
4247   }
4248 }
4249
4250 static guint64
4251 add_offset (guint64 offset, guint64 advance)
4252 {
4253   /* Avoid 64-bit overflow by clamping */
4254   if (offset > G_MAXUINT64 - advance)
4255     return G_MAXUINT64;
4256   return offset + advance;
4257 }
4258
4259 static GstFlowReturn
4260 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4261 {
4262   guint64 length = 0;
4263   guint32 fourcc = 0;
4264   GstBuffer *buf = NULL;
4265   GstFlowReturn ret = GST_FLOW_OK;
4266   guint64 cur_offset = qtdemux->offset;
4267   GstMapInfo map;
4268
4269   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4270   if (G_UNLIKELY (ret != GST_FLOW_OK))
4271     goto beach;
4272   gst_buffer_map (buf, &map, GST_MAP_READ);
4273   if (G_LIKELY (map.size >= 8))
4274     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4275   gst_buffer_unmap (buf, &map);
4276   gst_buffer_unref (buf);
4277
4278   /* maybe we already got most we needed, so only consider this eof */
4279   if (G_UNLIKELY (length == 0)) {
4280     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4281         (_("Invalid atom size.")),
4282         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4283             GST_FOURCC_ARGS (fourcc)));
4284     ret = GST_FLOW_EOS;
4285     goto beach;
4286   }
4287
4288   switch (fourcc) {
4289     case FOURCC_moof:
4290       /* record for later parsing when needed */
4291       if (!qtdemux->moof_offset) {
4292         qtdemux->moof_offset = qtdemux->offset;
4293       }
4294       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4295         /* FIXME */
4296       } else {
4297         qtdemux->offset += length;      /* skip moof and keep going */
4298       }
4299       if (qtdemux->got_moov) {
4300         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4301         ret = GST_FLOW_EOS;
4302         goto beach;
4303       }
4304       break;
4305     case FOURCC_mdat:
4306     case FOURCC_free:
4307     case FOURCC_skip:
4308     case FOURCC_wide:
4309     case FOURCC_PICT:
4310     case FOURCC_pnot:
4311     {
4312       GST_LOG_OBJECT (qtdemux,
4313           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4314           GST_FOURCC_ARGS (fourcc), cur_offset);
4315       qtdemux->offset = add_offset (qtdemux->offset, length);
4316       break;
4317     }
4318     case FOURCC_moov:
4319     {
4320       GstBuffer *moov = NULL;
4321
4322       if (qtdemux->got_moov) {
4323         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4324         qtdemux->offset = add_offset (qtdemux->offset, length);
4325         goto beach;
4326       }
4327
4328       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4329       if (ret != GST_FLOW_OK)
4330         goto beach;
4331       gst_buffer_map (moov, &map, GST_MAP_READ);
4332
4333       if (length != map.size) {
4334         /* Some files have a 'moov' atom at the end of the file which contains
4335          * a terminal 'free' atom where the body of the atom is missing.
4336          * Check for, and permit, this special case.
4337          */
4338         if (map.size >= 8) {
4339           guint8 *final_data = map.data + (map.size - 8);
4340           guint32 final_length = QT_UINT32 (final_data);
4341           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4342
4343           if (final_fourcc == FOURCC_free
4344               && map.size + final_length - 8 == length) {
4345             /* Ok, we've found that special case. Allocate a new buffer with
4346              * that free atom actually present. */
4347             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4348             gst_buffer_fill (newmoov, 0, map.data, map.size);
4349             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4350             gst_buffer_unmap (moov, &map);
4351             gst_buffer_unref (moov);
4352             moov = newmoov;
4353             gst_buffer_map (moov, &map, GST_MAP_READ);
4354           }
4355         }
4356       }
4357
4358       if (length != map.size) {
4359         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4360             (_("This file is incomplete and cannot be played.")),
4361             ("We got less than expected (received %" G_GSIZE_FORMAT
4362                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4363                 (guint) length, cur_offset));
4364         gst_buffer_unmap (moov, &map);
4365         gst_buffer_unref (moov);
4366         ret = GST_FLOW_ERROR;
4367         goto beach;
4368       }
4369       qtdemux->offset += length;
4370
4371       qtdemux_parse_moov (qtdemux, map.data, length);
4372       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4373
4374       qtdemux_parse_tree (qtdemux);
4375       if (qtdemux->moov_node_compressed) {
4376         g_node_destroy (qtdemux->moov_node_compressed);
4377         g_free (qtdemux->moov_node->data);
4378       }
4379       qtdemux->moov_node_compressed = NULL;
4380       g_node_destroy (qtdemux->moov_node);
4381       qtdemux->moov_node = NULL;
4382       gst_buffer_unmap (moov, &map);
4383       gst_buffer_unref (moov);
4384       qtdemux->got_moov = TRUE;
4385
4386       break;
4387     }
4388     case FOURCC_ftyp:
4389     {
4390       GstBuffer *ftyp = NULL;
4391
4392       /* extract major brand; might come in handy for ISO vs QT issues */
4393       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4394       if (ret != GST_FLOW_OK)
4395         goto beach;
4396       qtdemux->offset += length;
4397       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4398       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4399       gst_buffer_unmap (ftyp, &map);
4400       gst_buffer_unref (ftyp);
4401       break;
4402     }
4403     case FOURCC_uuid:
4404     {
4405       GstBuffer *uuid = NULL;
4406
4407       /* uuid are extension atoms */
4408       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4409       if (ret != GST_FLOW_OK)
4410         goto beach;
4411       qtdemux->offset += length;
4412       gst_buffer_map (uuid, &map, GST_MAP_READ);
4413       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4414       gst_buffer_unmap (uuid, &map);
4415       gst_buffer_unref (uuid);
4416       break;
4417     }
4418     case FOURCC_sidx:
4419     {
4420       GstBuffer *sidx = NULL;
4421       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4422       if (ret != GST_FLOW_OK)
4423         goto beach;
4424       qtdemux->offset += length;
4425       gst_buffer_map (sidx, &map, GST_MAP_READ);
4426       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4427       gst_buffer_unmap (sidx, &map);
4428       gst_buffer_unref (sidx);
4429       break;
4430     }
4431     default:
4432     {
4433       GstBuffer *unknown = NULL;
4434
4435       GST_LOG_OBJECT (qtdemux,
4436           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4437           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4438           cur_offset);
4439       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4440       if (ret != GST_FLOW_OK)
4441         goto beach;
4442       gst_buffer_map (unknown, &map, GST_MAP_READ);
4443       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4444       gst_buffer_unmap (unknown, &map);
4445       gst_buffer_unref (unknown);
4446       qtdemux->offset += length;
4447       break;
4448     }
4449   }
4450
4451 beach:
4452   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4453     /* digested all data, show what we have */
4454     qtdemux_prepare_streams (qtdemux);
4455     ret = qtdemux_expose_streams (qtdemux);
4456
4457     qtdemux->state = QTDEMUX_STATE_MOVIE;
4458     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4459         qtdemux->state);
4460     return ret;
4461   }
4462   return ret;
4463 }
4464
4465 /* Seeks to the previous keyframe of the indexed stream and
4466  * aligns other streams with respect to the keyframe timestamp
4467  * of indexed stream. Only called in case of Reverse Playback
4468  */
4469 static GstFlowReturn
4470 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4471 {
4472   guint8 n = 0;
4473   guint32 seg_idx = 0, k_index = 0;
4474   guint32 ref_seg_idx, ref_k_index;
4475   GstClockTime k_pos = 0, last_stop = 0;
4476   QtDemuxSegment *seg = NULL;
4477   QtDemuxStream *ref_str = NULL;
4478   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4479   guint64 target_ts;
4480
4481   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4482    * and finally align all the other streams on that timestamp with their
4483    * respective keyframes */
4484   for (n = 0; n < qtdemux->n_streams; n++) {
4485     QtDemuxStream *str = qtdemux->streams[n];
4486
4487     /* No candidate yet, take the first stream */
4488     if (!ref_str) {
4489       ref_str = str;
4490       continue;
4491     }
4492
4493     /* So that stream has a segment, we prefer video streams */
4494     if (str->subtype == FOURCC_vide) {
4495       ref_str = str;
4496       break;
4497     }
4498   }
4499
4500   if (G_UNLIKELY (!ref_str)) {
4501     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4502     goto eos;
4503   }
4504
4505   if (G_UNLIKELY (!ref_str->from_sample)) {
4506     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4507     goto eos;
4508   }
4509
4510   /* So that stream has been playing from from_sample to to_sample. We will
4511    * get the timestamp of the previous sample and search for a keyframe before
4512    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4513   if (ref_str->subtype == FOURCC_vide) {
4514     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4515         ref_str->from_sample - 1, FALSE);
4516   } else {
4517     if (ref_str->from_sample >= 10)
4518       k_index = ref_str->from_sample - 10;
4519     else
4520       k_index = 0;
4521   }
4522
4523   target_ts =
4524       ref_str->samples[k_index].timestamp +
4525       ref_str->samples[k_index].pts_offset;
4526
4527   /* get current segment for that stream */
4528   seg = &ref_str->segments[ref_str->segment_index];
4529   /* Use segment start in original timescale for comparisons */
4530   seg_media_start_mov = seg->trak_media_start;
4531
4532   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4533       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4534       k_index, target_ts, seg_media_start_mov,
4535       GST_TIME_ARGS (seg->media_start));
4536
4537   /* Crawl back through segments to find the one containing this I frame */
4538   while (target_ts < seg_media_start_mov) {
4539     GST_DEBUG_OBJECT (qtdemux,
4540         "keyframe position (sample %u) is out of segment %u " " target %"
4541         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4542         ref_str->segment_index, target_ts, seg_media_start_mov);
4543
4544     if (G_UNLIKELY (!ref_str->segment_index)) {
4545       /* Reached first segment, let's consider it's EOS */
4546       goto eos;
4547     }
4548     ref_str->segment_index--;
4549     seg = &ref_str->segments[ref_str->segment_index];
4550     /* Use segment start in original timescale for comparisons */
4551     seg_media_start_mov = seg->trak_media_start;
4552   }
4553   /* Calculate time position of the keyframe and where we should stop */
4554   k_pos =
4555       QTSTREAMTIME_TO_GSTTIME (ref_str,
4556       target_ts - seg->trak_media_start) + seg->time;
4557   last_stop =
4558       QTSTREAMTIME_TO_GSTTIME (ref_str,
4559       ref_str->samples[ref_str->from_sample].timestamp -
4560       seg->trak_media_start) + seg->time;
4561
4562   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4563       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4564       k_index, GST_TIME_ARGS (k_pos));
4565
4566   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4567   qtdemux->segment.position = last_stop;
4568   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4569       GST_TIME_ARGS (last_stop));
4570
4571   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4572     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4573     goto eos;
4574   }
4575
4576   ref_seg_idx = ref_str->segment_index;
4577   ref_k_index = k_index;
4578
4579   /* Align them all on this */
4580   for (n = 0; n < qtdemux->n_streams; n++) {
4581     guint32 index = 0;
4582     GstClockTime seg_time = 0;
4583     QtDemuxStream *str = qtdemux->streams[n];
4584
4585     /* aligning reference stream again might lead to backing up to yet another
4586      * keyframe (due to timestamp rounding issues),
4587      * potentially putting more load on downstream; so let's try to avoid */
4588     if (str == ref_str) {
4589       seg_idx = ref_seg_idx;
4590       seg = &str->segments[seg_idx];
4591       k_index = ref_k_index;
4592       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4593           "sample at index %d", n, ref_str->segment_index, k_index);
4594     } else {
4595       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4596       GST_DEBUG_OBJECT (qtdemux,
4597           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4598           seg_idx, GST_TIME_ARGS (k_pos));
4599
4600       /* get segment and time in the segment */
4601       seg = &str->segments[seg_idx];
4602       seg_time = k_pos - seg->time;
4603
4604       /* get the media time in the segment.
4605        * No adjustment for empty "filler" segments */
4606       if (seg->media_start != GST_CLOCK_TIME_NONE)
4607         seg_time += seg->media_start;
4608
4609       /* get the index of the sample with media time */
4610       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4611       GST_DEBUG_OBJECT (qtdemux,
4612           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4613           GST_TIME_ARGS (seg_time), index);
4614
4615       /* find previous keyframe */
4616       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4617     }
4618
4619     /* Remember until where we want to go */
4620     str->to_sample = str->from_sample - 1;
4621     /* Define our time position */
4622     target_ts =
4623         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4624     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4625     if (seg->media_start != GST_CLOCK_TIME_NONE)
4626       str->time_position -= seg->media_start;
4627
4628     /* Now seek back in time */
4629     gst_qtdemux_move_stream (qtdemux, str, k_index);
4630     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4631         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4632         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4633   }
4634
4635   return GST_FLOW_OK;
4636
4637 eos:
4638   return GST_FLOW_EOS;
4639 }
4640
4641 /*
4642  * Gets the current qt segment start, stop and position for the
4643  * given time offset. This is used in update_segment()
4644  */
4645 static void
4646 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4647     QtDemuxStream * stream, GstClockTime offset,
4648     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4649 {
4650   GstClockTime seg_time;
4651   GstClockTime start, stop, time;
4652   QtDemuxSegment *segment;
4653
4654   segment = &stream->segments[stream->segment_index];
4655
4656   /* get time in this segment */
4657   seg_time = (offset - segment->time) * segment->rate;
4658
4659   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4660       GST_TIME_ARGS (seg_time));
4661
4662   if (G_UNLIKELY (seg_time > segment->duration)) {
4663     GST_LOG_OBJECT (stream->pad,
4664         "seg_time > segment->duration %" GST_TIME_FORMAT,
4665         GST_TIME_ARGS (segment->duration));
4666     seg_time = segment->duration;
4667   }
4668
4669   /* qtdemux->segment.stop is in outside-time-realm, whereas
4670    * segment->media_stop is in track-time-realm.
4671    *
4672    * In order to compare the two, we need to bring segment.stop
4673    * into the track-time-realm
4674    *
4675    * FIXME - does this comment still hold? Don't see any conversion here */
4676
4677   stop = qtdemux->segment.stop;
4678   if (stop == GST_CLOCK_TIME_NONE)
4679     stop = qtdemux->segment.duration;
4680   if (stop == GST_CLOCK_TIME_NONE)
4681     stop = segment->media_stop;
4682   else
4683     stop =
4684         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4685
4686   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4687     start = segment->time + seg_time;
4688     time = offset;
4689     stop = start - seg_time + segment->duration;
4690   } else if (qtdemux->segment.rate >= 0) {
4691     start = MIN (segment->media_start + seg_time, stop);
4692     time = offset;
4693   } else {
4694     if (segment->media_start >= qtdemux->segment.start) {
4695       time = segment->time;
4696     } else {
4697       time = segment->time + (qtdemux->segment.start - segment->media_start);
4698     }
4699
4700     start = MAX (segment->media_start, qtdemux->segment.start);
4701     stop = MIN (segment->media_start + seg_time, stop);
4702   }
4703
4704   *_start = start;
4705   *_stop = stop;
4706   *_time = time;
4707 }
4708
4709 /*
4710  * Updates the qt segment used for the stream and pushes a new segment event
4711  * downstream on this stream's pad.
4712  */
4713 static gboolean
4714 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4715     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4716     GstClockTime * _stop)
4717 {
4718   QtDemuxSegment *segment;
4719   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4720   gdouble rate;
4721   GstEvent *event;
4722
4723   /* update the current segment */
4724   stream->segment_index = seg_idx;
4725
4726   /* get the segment */
4727   segment = &stream->segments[seg_idx];
4728
4729   if (G_UNLIKELY (offset < segment->time)) {
4730     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4731         GST_TIME_ARGS (segment->time));
4732     return FALSE;
4733   }
4734
4735   /* segment lies beyond total indicated duration */
4736   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4737           segment->time > qtdemux->segment.duration)) {
4738     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4739         " < segment->time %" GST_TIME_FORMAT,
4740         GST_TIME_ARGS (qtdemux->segment.duration),
4741         GST_TIME_ARGS (segment->time));
4742     return FALSE;
4743   }
4744
4745   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4746       &start, &stop, &time);
4747
4748   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4749       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4750       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4751
4752   /* combine global rate with that of the segment */
4753   rate = segment->rate * qtdemux->segment.rate;
4754
4755   /* Copy flags from main segment */
4756   stream->segment.flags = qtdemux->segment.flags;
4757
4758   /* update the segment values used for clipping */
4759   stream->segment.offset = qtdemux->segment.offset;
4760   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4761   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4762   stream->segment.rate = rate;
4763   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4764       stream->cslg_shift);
4765   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4766       stream->cslg_shift);
4767   stream->segment.time = time;
4768   stream->segment.position = stream->segment.start;
4769
4770   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4771       &stream->segment);
4772
4773   /* now prepare and send the segment */
4774   if (stream->pad) {
4775     event = gst_event_new_segment (&stream->segment);
4776     if (qtdemux->segment_seqnum) {
4777       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4778     }
4779     gst_pad_push_event (stream->pad, event);
4780     /* assume we can send more data now */
4781     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4782     /* clear to send tags on this pad now */
4783     gst_qtdemux_push_tags (qtdemux, stream);
4784   }
4785
4786   if (_start)
4787     *_start = start;
4788   if (_stop)
4789     *_stop = stop;
4790
4791   return TRUE;
4792 }
4793
4794 /* activate the given segment number @seg_idx of @stream at time @offset.
4795  * @offset is an absolute global position over all the segments.
4796  *
4797  * This will push out a NEWSEGMENT event with the right values and
4798  * position the stream index to the first decodable sample before
4799  * @offset.
4800  */
4801 static gboolean
4802 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4803     guint32 seg_idx, GstClockTime offset)
4804 {
4805   QtDemuxSegment *segment;
4806   guint32 index, kf_index;
4807   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4808
4809   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4810       seg_idx, GST_TIME_ARGS (offset));
4811
4812   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4813           &start, &stop))
4814     return FALSE;
4815
4816   segment = &stream->segments[stream->segment_index];
4817
4818   /* in the fragmented case, we pick a fragment that starts before our
4819    * desired position and rely on downstream to wait for a keyframe
4820    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4821    * tfra entries tells us which trun/sample the key unit is in, but we don't
4822    * make use of this additional information at the moment) */
4823   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4824     stream->to_sample = G_MAXUINT32;
4825     return TRUE;
4826   } else {
4827     /* well, it will be taken care of below */
4828     qtdemux->fragmented_seek_pending = FALSE;
4829     /* FIXME ideally the do_fragmented_seek can be done right here,
4830      * rather than at loop level
4831      * (which might even allow handling edit lists in a fragmented file) */
4832   }
4833
4834   /* We don't need to look for a sample in push-based */
4835   if (!qtdemux->pullbased)
4836     return TRUE;
4837
4838   /* and move to the keyframe before the indicated media time of the
4839    * segment */
4840   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4841     if (qtdemux->segment.rate >= 0) {
4842       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4843       stream->to_sample = G_MAXUINT32;
4844       GST_DEBUG_OBJECT (stream->pad,
4845           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4846           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4847           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4848     } else {
4849       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4850       stream->to_sample = index;
4851       GST_DEBUG_OBJECT (stream->pad,
4852           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4853           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4854           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4855     }
4856   } else {
4857     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4858         "this is an empty segment");
4859     return TRUE;
4860   }
4861
4862   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4863    * encountered an error and printed a message so we return appropriately */
4864   if (index == -1)
4865     return FALSE;
4866
4867   /* we're at the right spot */
4868   if (index == stream->sample_index) {
4869     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4870     return TRUE;
4871   }
4872
4873   /* find keyframe of the target index */
4874   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4875
4876 /* *INDENT-OFF* */
4877 /* indent does stupid stuff with stream->samples[].timestamp */
4878
4879   /* if we move forwards, we don't have to go back to the previous
4880    * keyframe since we already sent that. We can also just jump to
4881    * the keyframe right before the target index if there is one. */
4882   if (index > stream->sample_index) {
4883     /* moving forwards check if we move past a keyframe */
4884     if (kf_index > stream->sample_index) {
4885       GST_DEBUG_OBJECT (stream->pad,
4886            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4887            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4888            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4889       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4890     } else {
4891       GST_DEBUG_OBJECT (stream->pad,
4892           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4893           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4894           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4895     }
4896   } else {
4897     GST_DEBUG_OBJECT (stream->pad,
4898         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4899         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4900         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4901     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4902   }
4903
4904 /* *INDENT-ON* */
4905
4906   return TRUE;
4907 }
4908
4909 /* prepare to get the current sample of @stream, getting essential values.
4910  *
4911  * This function will also prepare and send the segment when needed.
4912  *
4913  * Return FALSE if the stream is EOS.
4914  *
4915  * PULL-BASED
4916  */
4917 static gboolean
4918 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4919     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4920     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4921     gboolean * keyframe)
4922 {
4923   QtDemuxSample *sample;
4924   GstClockTime time_position;
4925   guint32 seg_idx;
4926
4927   g_return_val_if_fail (stream != NULL, FALSE);
4928
4929   time_position = stream->time_position;
4930   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4931     goto eos;
4932
4933   seg_idx = stream->segment_index;
4934   if (G_UNLIKELY (seg_idx == -1)) {
4935     /* find segment corresponding to time_position if we are looking
4936      * for a segment. */
4937     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4938   }
4939
4940   /* different segment, activate it, sample_index will be set. */
4941   if (G_UNLIKELY (stream->segment_index != seg_idx))
4942     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4943
4944   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4945                   segment_index]))) {
4946     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4947
4948     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4949         " prepare empty sample");
4950
4951     *empty = TRUE;
4952     *pts = *dts = time_position;
4953     *duration = seg->duration - (time_position - seg->time);
4954
4955     return TRUE;
4956   }
4957
4958   *empty = FALSE;
4959
4960   if (stream->sample_index == -1)
4961     stream->sample_index = 0;
4962
4963   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4964       stream->sample_index, stream->n_samples);
4965
4966   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4967     if (!qtdemux->fragmented)
4968       goto eos;
4969
4970     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4971     do {
4972       GstFlowReturn flow;
4973
4974       GST_OBJECT_LOCK (qtdemux);
4975       flow = qtdemux_add_fragmented_samples (qtdemux);
4976       GST_OBJECT_UNLOCK (qtdemux);
4977
4978       if (flow != GST_FLOW_OK)
4979         goto eos;
4980     }
4981     while (stream->sample_index >= stream->n_samples);
4982   }
4983
4984   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4985     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4986         stream->sample_index);
4987     return FALSE;
4988   }
4989
4990   /* now get the info for the sample we're at */
4991   sample = &stream->samples[stream->sample_index];
4992
4993   *dts = QTSAMPLE_DTS (stream, sample);
4994   *pts = QTSAMPLE_PTS (stream, sample);
4995   *offset = sample->offset;
4996   *size = sample->size;
4997   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4998   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4999
5000   return TRUE;
5001
5002   /* special cases */
5003 eos:
5004   {
5005     stream->time_position = GST_CLOCK_TIME_NONE;
5006     return FALSE;
5007   }
5008 }
5009
5010 /* move to the next sample in @stream.
5011  *
5012  * Moves to the next segment when needed.
5013  */
5014 static void
5015 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5016 {
5017   QtDemuxSample *sample;
5018   QtDemuxSegment *segment;
5019
5020   /* get current segment */
5021   segment = &stream->segments[stream->segment_index];
5022
5023   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5024     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5025     goto next_segment;
5026   }
5027
5028   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5029     /* Mark the stream as EOS */
5030     GST_DEBUG_OBJECT (qtdemux,
5031         "reached max allowed sample %u, mark EOS", stream->to_sample);
5032     stream->time_position = GST_CLOCK_TIME_NONE;
5033     return;
5034   }
5035
5036   /* move to next sample */
5037   stream->sample_index++;
5038   stream->offset_in_sample = 0;
5039
5040   /* reached the last sample, we need the next segment */
5041   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5042     goto next_segment;
5043
5044   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5045     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5046         stream->sample_index);
5047     return;
5048   }
5049
5050   /* get next sample */
5051   sample = &stream->samples[stream->sample_index];
5052
5053   /* see if we are past the segment */
5054   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5055     goto next_segment;
5056
5057   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5058     /* inside the segment, update time_position, looks very familiar to
5059      * GStreamer segments, doesn't it? */
5060     stream->time_position =
5061         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5062   } else {
5063     /* not yet in segment, time does not yet increment. This means
5064      * that we are still prerolling keyframes to the decoder so it can
5065      * decode the first sample of the segment. */
5066     stream->time_position = segment->time;
5067   }
5068   return;
5069
5070   /* move to the next segment */
5071 next_segment:
5072   {
5073     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5074
5075     if (stream->segment_index == stream->n_segments - 1) {
5076       /* are we at the end of the last segment, we're EOS */
5077       stream->time_position = GST_CLOCK_TIME_NONE;
5078     } else {
5079       /* else we're only at the end of the current segment */
5080       stream->time_position = segment->stop_time;
5081     }
5082     /* make sure we select a new segment */
5083
5084     /* accumulate previous segments */
5085     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5086       stream->accumulated_base +=
5087           (stream->segment.stop -
5088           stream->segment.start) / ABS (stream->segment.rate);
5089
5090     stream->segment_index = -1;
5091   }
5092 }
5093
5094 static void
5095 gst_qtdemux_sync_streams (GstQTDemux * demux)
5096 {
5097   gint i;
5098
5099   if (demux->n_streams <= 1)
5100     return;
5101
5102   for (i = 0; i < demux->n_streams; i++) {
5103     QtDemuxStream *stream;
5104     GstClockTime end_time;
5105
5106     stream = demux->streams[i];
5107
5108     if (!stream->pad)
5109       continue;
5110
5111     /* TODO advance time on subtitle streams here, if any some day */
5112
5113     /* some clips/trailers may have unbalanced streams at the end,
5114      * so send EOS on shorter stream to prevent stalling others */
5115
5116     /* do not mess with EOS if SEGMENT seeking */
5117     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5118       continue;
5119
5120     if (demux->pullbased) {
5121       /* loop mode is sample time based */
5122       if (!STREAM_IS_EOS (stream))
5123         continue;
5124     } else {
5125       /* push mode is byte position based */
5126       if (stream->n_samples &&
5127           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5128         continue;
5129     }
5130
5131     if (stream->sent_eos)
5132       continue;
5133
5134     /* only act if some gap */
5135     end_time = stream->segments[stream->n_segments - 1].stop_time;
5136     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5137         ", stream end: %" GST_TIME_FORMAT,
5138         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5139     if (GST_CLOCK_TIME_IS_VALID (end_time)
5140         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5141       GstEvent *event;
5142
5143       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5144           GST_PAD_NAME (stream->pad));
5145       stream->sent_eos = TRUE;
5146       event = gst_event_new_eos ();
5147       if (demux->segment_seqnum)
5148         gst_event_set_seqnum (event, demux->segment_seqnum);
5149       gst_pad_push_event (stream->pad, event);
5150     }
5151   }
5152 }
5153
5154 /* EOS and NOT_LINKED need to be combined. This means that we return:
5155  *
5156  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5157  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5158  */
5159 static GstFlowReturn
5160 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5161     GstFlowReturn ret)
5162 {
5163   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5164
5165   if (stream->pad)
5166     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5167         ret);
5168   else
5169     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5170
5171   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5172   return ret;
5173 }
5174
5175 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5176  * completely clipped
5177  *
5178  * Should be used only with raw buffers */
5179 static GstBuffer *
5180 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5181     GstBuffer * buf)
5182 {
5183   guint64 start, stop, cstart, cstop, diff;
5184   GstClockTime pts, duration;
5185   gsize size, osize;
5186   gint num_rate, denom_rate;
5187   gint frame_size;
5188   gboolean clip_data;
5189   guint offset;
5190
5191   osize = size = gst_buffer_get_size (buf);
5192   offset = 0;
5193
5194   /* depending on the type, setup the clip parameters */
5195   if (stream->subtype == FOURCC_soun) {
5196     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5197     num_rate = GST_SECOND;
5198     denom_rate = (gint) CUR_STREAM (stream)->rate;
5199     clip_data = TRUE;
5200   } else if (stream->subtype == FOURCC_vide) {
5201     frame_size = size;
5202     num_rate = CUR_STREAM (stream)->fps_n;
5203     denom_rate = CUR_STREAM (stream)->fps_d;
5204     clip_data = FALSE;
5205   } else
5206     goto wrong_type;
5207
5208   if (frame_size <= 0)
5209     goto bad_frame_size;
5210
5211   /* we can only clip if we have a valid pts */
5212   pts = GST_BUFFER_PTS (buf);
5213   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5214     goto no_pts;
5215
5216   duration = GST_BUFFER_DURATION (buf);
5217
5218   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5219     duration =
5220         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5221   }
5222
5223   start = pts;
5224   stop = start + duration;
5225
5226   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5227               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5228     goto clipped;
5229
5230   /* see if some clipping happened */
5231   diff = cstart - start;
5232   if (diff > 0) {
5233     pts += diff;
5234     duration -= diff;
5235
5236     if (clip_data) {
5237       /* bring clipped time to samples and to bytes */
5238       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5239       diff *= frame_size;
5240
5241       GST_DEBUG_OBJECT (qtdemux,
5242           "clipping start to %" GST_TIME_FORMAT " %"
5243           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5244
5245       offset = diff;
5246       size -= diff;
5247     }
5248   }
5249   diff = stop - cstop;
5250   if (diff > 0) {
5251     duration -= diff;
5252
5253     if (clip_data) {
5254       /* bring clipped time to samples and then to bytes */
5255       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5256       diff *= frame_size;
5257       GST_DEBUG_OBJECT (qtdemux,
5258           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5259           " bytes", GST_TIME_ARGS (cstop), diff);
5260       size -= diff;
5261     }
5262   }
5263
5264   if (offset != 0 || size != osize)
5265     gst_buffer_resize (buf, offset, size);
5266
5267   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5268   GST_BUFFER_PTS (buf) = pts;
5269   GST_BUFFER_DURATION (buf) = duration;
5270
5271   return buf;
5272
5273   /* dropped buffer */
5274 wrong_type:
5275   {
5276     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5277     return buf;
5278   }
5279 bad_frame_size:
5280   {
5281     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5282     return buf;
5283   }
5284 no_pts:
5285   {
5286     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5287     return buf;
5288   }
5289 clipped:
5290   {
5291     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5292     gst_buffer_unref (buf);
5293     return NULL;
5294   }
5295 }
5296
5297 static GstBuffer *
5298 gst_qtdemux_align_buffer (GstQTDemux * demux,
5299     GstBuffer * buffer, gsize alignment)
5300 {
5301   GstMapInfo map;
5302
5303   gst_buffer_map (buffer, &map, GST_MAP_READ);
5304
5305   if (map.size < sizeof (guintptr)) {
5306     gst_buffer_unmap (buffer, &map);
5307     return buffer;
5308   }
5309
5310   if (((guintptr) map.data) & (alignment - 1)) {
5311     GstBuffer *new_buffer;
5312     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5313
5314     new_buffer = gst_buffer_new_allocate (NULL,
5315         gst_buffer_get_size (buffer), &params);
5316
5317     /* Copy data "by hand", so ensure alignment is kept: */
5318     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5319
5320     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5321     GST_DEBUG_OBJECT (demux,
5322         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5323         alignment);
5324
5325     gst_buffer_unmap (buffer, &map);
5326     gst_buffer_unref (buffer);
5327
5328     return new_buffer;
5329   }
5330
5331   gst_buffer_unmap (buffer, &map);
5332   return buffer;
5333 }
5334
5335 /* the input buffer metadata must be writable,
5336  * but time/duration etc not yet set and need not be preserved */
5337 static GstBuffer *
5338 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5339     GstBuffer * buf)
5340 {
5341   GstMapInfo map;
5342   guint nsize = 0;
5343   gchar *str;
5344
5345   /* not many cases for now */
5346   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5347     /* send a one time dvd clut event */
5348     if (stream->pending_event && stream->pad)
5349       gst_pad_push_event (stream->pad, stream->pending_event);
5350     stream->pending_event = NULL;
5351   }
5352
5353   if (G_UNLIKELY (stream->subtype != FOURCC_text
5354           && stream->subtype != FOURCC_sbtl &&
5355           stream->subtype != FOURCC_subp)) {
5356     return buf;
5357   }
5358
5359   gst_buffer_map (buf, &map, GST_MAP_READ);
5360
5361   /* empty buffer is sent to terminate previous subtitle */
5362   if (map.size <= 2) {
5363     gst_buffer_unmap (buf, &map);
5364     gst_buffer_unref (buf);
5365     return NULL;
5366   }
5367   if (stream->subtype == FOURCC_subp) {
5368     /* That's all the processing needed for subpictures */
5369     gst_buffer_unmap (buf, &map);
5370     return buf;
5371   }
5372
5373   nsize = GST_READ_UINT16_BE (map.data);
5374   nsize = MIN (nsize, map.size - 2);
5375
5376   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5377       nsize, map.size);
5378
5379   /* takes care of UTF-8 validation or UTF-16 recognition,
5380    * no other encoding expected */
5381   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5382   gst_buffer_unmap (buf, &map);
5383   if (str) {
5384     gst_buffer_unref (buf);
5385     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5386   } else {
5387     /* this should not really happen unless the subtitle is corrupted */
5388     gst_buffer_unref (buf);
5389     buf = NULL;
5390   }
5391
5392   /* FIXME ? convert optional subsequent style info to markup */
5393
5394   return buf;
5395 }
5396
5397 /* Sets a buffer's attributes properly and pushes it downstream.
5398  * Also checks for additional actions and custom processing that may
5399  * need to be done first.
5400  */
5401 static GstFlowReturn
5402 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5403     QtDemuxStream * stream, GstBuffer * buf,
5404     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5405     gboolean keyframe, GstClockTime position, guint64 byte_position)
5406 {
5407   GstFlowReturn ret = GST_FLOW_OK;
5408
5409   /* offset the timestamps according to the edit list */
5410
5411   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5412     gchar *url;
5413     GstMapInfo map;
5414
5415     gst_buffer_map (buf, &map, GST_MAP_READ);
5416     url = g_strndup ((gchar *) map.data, map.size);
5417     gst_buffer_unmap (buf, &map);
5418     if (url != NULL && strlen (url) != 0) {
5419       /* we have RTSP redirect now */
5420       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5421           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5422               gst_structure_new ("redirect",
5423                   "new-location", G_TYPE_STRING, url, NULL)));
5424       qtdemux->posted_redirect = TRUE;
5425     } else {
5426       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5427           "posting");
5428     }
5429     g_free (url);
5430   }
5431
5432   /* position reporting */
5433   if (qtdemux->segment.rate >= 0) {
5434     qtdemux->segment.position = position;
5435     gst_qtdemux_sync_streams (qtdemux);
5436   }
5437
5438   if (G_UNLIKELY (!stream->pad)) {
5439     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5440     gst_buffer_unref (buf);
5441     goto exit;
5442   }
5443
5444   /* send out pending buffers */
5445   while (stream->buffers) {
5446     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5447
5448     if (G_UNLIKELY (stream->discont)) {
5449       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5450       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5451       stream->discont = FALSE;
5452     } else {
5453       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5454     }
5455
5456     if (stream->alignment > 1)
5457       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5458     gst_pad_push (stream->pad, buffer);
5459
5460     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5461   }
5462
5463   /* we're going to modify the metadata */
5464   buf = gst_buffer_make_writable (buf);
5465
5466   if (G_UNLIKELY (stream->need_process))
5467     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5468
5469   if (!buf) {
5470     goto exit;
5471   }
5472
5473   GST_BUFFER_DTS (buf) = dts;
5474   GST_BUFFER_PTS (buf) = pts;
5475   GST_BUFFER_DURATION (buf) = duration;
5476   GST_BUFFER_OFFSET (buf) = -1;
5477   GST_BUFFER_OFFSET_END (buf) = -1;
5478
5479   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5480     gst_buffer_append_memory (buf,
5481         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5482
5483   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5484     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5485   }
5486 #if 0
5487   if (G_UNLIKELY (qtdemux->element_index)) {
5488     GstClockTime stream_time;
5489
5490     stream_time =
5491         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5492         timestamp);
5493     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5494       GST_LOG_OBJECT (qtdemux,
5495           "adding association %" GST_TIME_FORMAT "-> %"
5496           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5497       gst_index_add_association (qtdemux->element_index,
5498           qtdemux->index_id,
5499           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5500           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5501           GST_FORMAT_BYTES, byte_position, NULL);
5502     }
5503   }
5504 #endif
5505
5506   if (stream->need_clip)
5507     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5508
5509   if (G_UNLIKELY (buf == NULL))
5510     goto exit;
5511
5512   if (G_UNLIKELY (stream->discont)) {
5513     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5514     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5515     stream->discont = FALSE;
5516   } else {
5517     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5518   }
5519
5520   if (!keyframe) {
5521     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5522     stream->on_keyframe = FALSE;
5523   } else {
5524     stream->on_keyframe = TRUE;
5525   }
5526
5527
5528   GST_LOG_OBJECT (qtdemux,
5529       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5530       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5531       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5532       GST_PAD_NAME (stream->pad));
5533
5534   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5535     GstStructure *crypto_info;
5536     QtDemuxCencSampleSetInfo *info =
5537         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5538     gint index;
5539     GstEvent *event;
5540
5541     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5542       gst_pad_push_event (stream->pad, event);
5543     }
5544
5545     if (info->crypto_info == NULL) {
5546       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5547       gst_buffer_unref (buf);
5548       goto exit;
5549     }
5550
5551     /* The end of the crypto_info array matches our n_samples position,
5552      * so count backward from there */
5553     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5554     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5555       /* steal structure from array */
5556       crypto_info = g_ptr_array_index (info->crypto_info, index);
5557       g_ptr_array_index (info->crypto_info, index) = NULL;
5558       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5559           info->crypto_info->len);
5560       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5561         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5562     } else {
5563       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5564           index, stream->sample_index);
5565     }
5566   }
5567
5568   if (stream->alignment > 1)
5569     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5570
5571   ret = gst_pad_push (stream->pad, buf);
5572
5573   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5574     /* mark position in stream, we'll need this to know when to send GAP event */
5575     stream->segment.position = pts + duration;
5576   }
5577
5578 exit:
5579   return ret;
5580 }
5581
5582 static const QtDemuxRandomAccessEntry *
5583 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5584     GstClockTime pos, gboolean after)
5585 {
5586   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5587   guint n_entries = stream->n_ra_entries;
5588   guint i;
5589
5590   /* we assume the table is sorted */
5591   for (i = 0; i < n_entries; ++i) {
5592     if (entries[i].ts > pos)
5593       break;
5594   }
5595
5596   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5597    * probably okay to assume that the index lists the very first fragment */
5598   if (i == 0)
5599     return &entries[0];
5600
5601   if (after)
5602     return &entries[i];
5603   else
5604     return &entries[i - 1];
5605 }
5606
5607 static gboolean
5608 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5609 {
5610   const QtDemuxRandomAccessEntry *best_entry = NULL;
5611   guint i;
5612
5613   GST_OBJECT_LOCK (qtdemux);
5614
5615   g_assert (qtdemux->n_streams > 0);
5616
5617   /* first see if we can determine where to go to using mfra,
5618    * before we start clearing things */
5619   for (i = 0; i < qtdemux->n_streams; i++) {
5620     const QtDemuxRandomAccessEntry *entry;
5621     QtDemuxStream *stream;
5622     gboolean is_audio_or_video;
5623
5624     stream = qtdemux->streams[i];
5625
5626     if (stream->ra_entries == NULL)
5627       continue;
5628
5629     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5630       is_audio_or_video = TRUE;
5631     else
5632       is_audio_or_video = FALSE;
5633
5634     entry =
5635         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5636         stream->time_position, !is_audio_or_video);
5637
5638     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5639         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5640
5641     stream->pending_seek = entry;
5642
5643     /* decide position to jump to just based on audio/video tracks, not subs */
5644     if (!is_audio_or_video)
5645       continue;
5646
5647     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5648       best_entry = entry;
5649   }
5650
5651   /* no luck, will handle seek otherwise */
5652   if (best_entry == NULL) {
5653     GST_OBJECT_UNLOCK (qtdemux);
5654     return FALSE;
5655   }
5656
5657   /* ok, now we can prepare for processing as of located moof */
5658   for (i = 0; i < qtdemux->n_streams; i++) {
5659     QtDemuxStream *stream;
5660
5661     stream = qtdemux->streams[i];
5662
5663     g_free (stream->samples);
5664     stream->samples = NULL;
5665     stream->n_samples = 0;
5666     stream->stbl_index = -1;    /* no samples have yet been parsed */
5667     stream->sample_index = -1;
5668
5669     if (stream->protection_scheme_info) {
5670       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5671       if (stream->protection_scheme_type == FOURCC_cenc) {
5672         QtDemuxCencSampleSetInfo *info =
5673             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5674         if (info->crypto_info) {
5675           g_ptr_array_free (info->crypto_info, TRUE);
5676           info->crypto_info = NULL;
5677         }
5678       }
5679     }
5680   }
5681
5682   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5683       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5684       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5685       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5686
5687   qtdemux->moof_offset = best_entry->moof_offset;
5688
5689   qtdemux_add_fragmented_samples (qtdemux);
5690
5691   GST_OBJECT_UNLOCK (qtdemux);
5692   return TRUE;
5693 }
5694
5695 static GstFlowReturn
5696 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5697 {
5698   GstFlowReturn ret = GST_FLOW_OK;
5699   GstBuffer *buf = NULL;
5700   QtDemuxStream *stream;
5701   GstClockTime min_time;
5702   guint64 offset = 0;
5703   GstClockTime dts = GST_CLOCK_TIME_NONE;
5704   GstClockTime pts = GST_CLOCK_TIME_NONE;
5705   GstClockTime duration = 0;
5706   gboolean keyframe = FALSE;
5707   guint sample_size = 0;
5708   gboolean empty = 0;
5709   guint size;
5710   gint index;
5711   gint i;
5712
5713   gst_qtdemux_push_pending_newsegment (qtdemux);
5714
5715   if (qtdemux->fragmented_seek_pending) {
5716     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5717     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
5718       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5719       qtdemux->fragmented_seek_pending = FALSE;
5720     } else {
5721       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
5722     }
5723   }
5724
5725   /* Figure out the next stream sample to output, min_time is expressed in
5726    * global time and runs over the edit list segments. */
5727   min_time = G_MAXUINT64;
5728   index = -1;
5729   for (i = 0; i < qtdemux->n_streams; i++) {
5730     GstClockTime position;
5731
5732     stream = qtdemux->streams[i];
5733     position = stream->time_position;
5734
5735     /* position of -1 is EOS */
5736     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5737       min_time = position;
5738       index = i;
5739     }
5740   }
5741   /* all are EOS */
5742   if (G_UNLIKELY (index == -1)) {
5743     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5744     goto eos;
5745   }
5746
5747   /* check for segment end */
5748   if (G_UNLIKELY (qtdemux->segment.stop != -1
5749           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5750               || (qtdemux->segment.rate < 0
5751                   && qtdemux->segment.start > min_time))
5752           && qtdemux->streams[index]->on_keyframe)) {
5753     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5754     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5755     goto eos_stream;
5756   }
5757
5758   /* gap events for subtitle streams */
5759   for (i = 0; i < qtdemux->n_streams; i++) {
5760     stream = qtdemux->streams[i];
5761     if (stream->pad && (stream->subtype == FOURCC_subp
5762             || stream->subtype == FOURCC_text
5763             || stream->subtype == FOURCC_sbtl)) {
5764       /* send one second gap events until the stream catches up */
5765       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5766       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5767           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5768           stream->segment.position + GST_SECOND < min_time) {
5769         GstEvent *gap =
5770             gst_event_new_gap (stream->segment.position, GST_SECOND);
5771         gst_pad_push_event (stream->pad, gap);
5772         stream->segment.position += GST_SECOND;
5773       }
5774     }
5775   }
5776
5777   stream = qtdemux->streams[index];
5778   /* fetch info for the current sample of this stream */
5779   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5780               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5781     goto eos_stream;
5782
5783   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5784   if (stream->new_caps) {
5785     gst_qtdemux_configure_stream (qtdemux, stream);
5786     qtdemux_do_allocation (qtdemux, stream);
5787   }
5788
5789   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5790   if (G_UNLIKELY (qtdemux->
5791           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5792     if (stream->subtype == FOURCC_vide && !keyframe) {
5793       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5794       goto next;
5795     }
5796   }
5797
5798   GST_DEBUG_OBJECT (qtdemux,
5799       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5800       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5801       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5802       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5803
5804   if (G_UNLIKELY (empty)) {
5805     /* empty segment, push a gap and move to the next one */
5806     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5807     stream->segment.position = pts + duration;
5808     goto next;
5809   }
5810
5811   /* hmm, empty sample, skip and move to next sample */
5812   if (G_UNLIKELY (sample_size <= 0))
5813     goto next;
5814
5815   /* last pushed sample was out of boundary, goto next sample */
5816   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5817     goto next;
5818
5819   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5820     size = sample_size;
5821   } else {
5822     GST_DEBUG_OBJECT (qtdemux,
5823         "size %d larger than stream max_buffer_size %d, trimming",
5824         sample_size, stream->max_buffer_size);
5825     size =
5826         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5827   }
5828
5829   if (qtdemux->cenc_aux_info_offset > 0) {
5830     GstMapInfo map;
5831     GstByteReader br;
5832     GstBuffer *aux_info = NULL;
5833
5834     /* pull the data stored before the sample */
5835     ret =
5836         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5837         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5838     if (G_UNLIKELY (ret != GST_FLOW_OK))
5839       goto beach;
5840     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5841     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5842     gst_byte_reader_init (&br, map.data + 8, map.size);
5843     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5844             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5845       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5846       gst_buffer_unmap (aux_info, &map);
5847       gst_buffer_unref (aux_info);
5848       ret = GST_FLOW_ERROR;
5849       goto beach;
5850     }
5851     gst_buffer_unmap (aux_info, &map);
5852     gst_buffer_unref (aux_info);
5853   }
5854
5855   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5856       offset);
5857
5858   if (stream->use_allocator) {
5859     /* if we have a per-stream allocator, use it */
5860     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5861   }
5862
5863   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5864       size, &buf);
5865   if (G_UNLIKELY (ret != GST_FLOW_OK))
5866     goto beach;
5867
5868   if (size != sample_size) {
5869     pts += gst_util_uint64_scale_int (GST_SECOND,
5870         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5871         stream->timescale);
5872     dts +=
5873         gst_util_uint64_scale_int (GST_SECOND,
5874         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5875         stream->timescale);
5876     duration =
5877         gst_util_uint64_scale_int (GST_SECOND,
5878         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5879   }
5880
5881   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5882       dts, pts, duration, keyframe, min_time, offset);
5883
5884   if (size != sample_size) {
5885     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5886     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5887
5888     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5889         sample->timestamp +
5890         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5891     if (time_position >= segment->media_start) {
5892       /* inside the segment, update time_position, looks very familiar to
5893        * GStreamer segments, doesn't it? */
5894       stream->time_position = (time_position - segment->media_start) +
5895           segment->time;
5896     } else {
5897       /* not yet in segment, time does not yet increment. This means
5898        * that we are still prerolling keyframes to the decoder so it can
5899        * decode the first sample of the segment. */
5900       stream->time_position = segment->time;
5901     }
5902   }
5903
5904   /* combine flows */
5905   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5906   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5907    * we have no more data for the pad to push */
5908   if (ret == GST_FLOW_EOS)
5909     ret = GST_FLOW_OK;
5910
5911   stream->offset_in_sample += size;
5912   if (stream->offset_in_sample >= sample_size) {
5913     gst_qtdemux_advance_sample (qtdemux, stream);
5914   }
5915   goto beach;
5916
5917 next:
5918   gst_qtdemux_advance_sample (qtdemux, stream);
5919
5920 beach:
5921   return ret;
5922
5923   /* special cases */
5924 eos:
5925   {
5926     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5927     ret = GST_FLOW_EOS;
5928     goto beach;
5929   }
5930 eos_stream:
5931   {
5932     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5933     /* EOS will be raised if all are EOS */
5934     ret = GST_FLOW_OK;
5935     goto beach;
5936   }
5937 }
5938
5939 static void
5940 gst_qtdemux_loop (GstPad * pad)
5941 {
5942   GstQTDemux *qtdemux;
5943   guint64 cur_offset;
5944   GstFlowReturn ret;
5945
5946   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5947
5948   cur_offset = qtdemux->offset;
5949   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5950       cur_offset, qt_demux_state_string (qtdemux->state));
5951
5952   switch (qtdemux->state) {
5953     case QTDEMUX_STATE_INITIAL:
5954     case QTDEMUX_STATE_HEADER:
5955       ret = gst_qtdemux_loop_state_header (qtdemux);
5956       break;
5957     case QTDEMUX_STATE_MOVIE:
5958       ret = gst_qtdemux_loop_state_movie (qtdemux);
5959       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5960         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5961       }
5962       break;
5963     default:
5964       /* ouch */
5965       goto invalid_state;
5966   }
5967
5968   /* if something went wrong, pause */
5969   if (ret != GST_FLOW_OK)
5970     goto pause;
5971
5972 done:
5973   gst_object_unref (qtdemux);
5974   return;
5975
5976   /* ERRORS */
5977 invalid_state:
5978   {
5979     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5980         (NULL), ("streaming stopped, invalid state"));
5981     gst_pad_pause_task (pad);
5982     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5983     goto done;
5984   }
5985 pause:
5986   {
5987     const gchar *reason = gst_flow_get_name (ret);
5988
5989     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5990
5991     gst_pad_pause_task (pad);
5992
5993     /* fatal errors need special actions */
5994     /* check EOS */
5995     if (ret == GST_FLOW_EOS) {
5996       if (qtdemux->n_streams == 0) {
5997         /* we have no streams, post an error */
5998         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5999       }
6000       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6001         gint64 stop;
6002
6003         if ((stop = qtdemux->segment.stop) == -1)
6004           stop = qtdemux->segment.duration;
6005
6006         if (qtdemux->segment.rate >= 0) {
6007           GstMessage *message;
6008           GstEvent *event;
6009
6010           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6011           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6012               GST_FORMAT_TIME, stop);
6013           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6014           if (qtdemux->segment_seqnum) {
6015             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6016             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6017           }
6018           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6019           gst_qtdemux_push_event (qtdemux, event);
6020         } else {
6021           GstMessage *message;
6022           GstEvent *event;
6023
6024           /*  For Reverse Playback */
6025           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6026           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6027               GST_FORMAT_TIME, qtdemux->segment.start);
6028           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6029               qtdemux->segment.start);
6030           if (qtdemux->segment_seqnum) {
6031             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6032             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6033           }
6034           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6035           gst_qtdemux_push_event (qtdemux, event);
6036         }
6037       } else {
6038         GstEvent *event;
6039
6040         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6041         event = gst_event_new_eos ();
6042         if (qtdemux->segment_seqnum)
6043           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6044         gst_qtdemux_push_event (qtdemux, event);
6045       }
6046     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6047       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6048       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6049     }
6050     goto done;
6051   }
6052 }
6053
6054 /*
6055  * has_next_entry
6056  *
6057  * Returns if there are samples to be played.
6058  */
6059 static gboolean
6060 has_next_entry (GstQTDemux * demux)
6061 {
6062   QtDemuxStream *stream;
6063   int i;
6064
6065   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6066
6067   for (i = 0; i < demux->n_streams; i++) {
6068     stream = demux->streams[i];
6069
6070     if (stream->sample_index == -1) {
6071       stream->sample_index = 0;
6072       stream->offset_in_sample = 0;
6073     }
6074
6075     if (stream->sample_index >= stream->n_samples) {
6076       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6077       continue;
6078     }
6079     GST_DEBUG_OBJECT (demux, "Found a sample");
6080     return TRUE;
6081   }
6082
6083   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6084   return FALSE;
6085 }
6086
6087 /*
6088  * next_entry_size
6089  *
6090  * Returns the size of the first entry at the current offset.
6091  * If -1, there are none (which means EOS or empty file).
6092  */
6093 static guint64
6094 next_entry_size (GstQTDemux * demux)
6095 {
6096   QtDemuxStream *stream;
6097   int i;
6098   int smallidx = -1;
6099   guint64 smalloffs = (guint64) - 1;
6100   QtDemuxSample *sample;
6101
6102   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6103       demux->offset);
6104
6105   for (i = 0; i < demux->n_streams; i++) {
6106     stream = demux->streams[i];
6107
6108     if (stream->sample_index == -1) {
6109       stream->sample_index = 0;
6110       stream->offset_in_sample = 0;
6111     }
6112
6113     if (stream->sample_index >= stream->n_samples) {
6114       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6115       continue;
6116     }
6117
6118     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6119       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6120           stream->sample_index);
6121       return -1;
6122     }
6123
6124     sample = &stream->samples[stream->sample_index];
6125
6126     GST_LOG_OBJECT (demux,
6127         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6128         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6129         sample->offset, sample->size);
6130
6131     if (((smalloffs == -1)
6132             || (sample->offset < smalloffs)) && (sample->size)) {
6133       smallidx = i;
6134       smalloffs = sample->offset;
6135     }
6136   }
6137
6138   GST_LOG_OBJECT (demux,
6139       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6140       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6141
6142   if (smallidx == -1)
6143     return -1;
6144
6145   stream = demux->streams[smallidx];
6146   sample = &stream->samples[stream->sample_index];
6147
6148   if (sample->offset >= demux->offset) {
6149     demux->todrop = sample->offset - demux->offset;
6150     return sample->size + demux->todrop;
6151   }
6152
6153   GST_DEBUG_OBJECT (demux,
6154       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6155   return -1;
6156 }
6157
6158 static void
6159 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6160 {
6161   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6162
6163   gst_element_post_message (GST_ELEMENT_CAST (demux),
6164       gst_message_new_element (GST_OBJECT_CAST (demux),
6165           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6166 }
6167
6168 static gboolean
6169 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6170 {
6171   GstEvent *event;
6172   gboolean res = 0;
6173
6174   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6175
6176   event =
6177       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6178       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6179       GST_SEEK_TYPE_NONE, -1);
6180
6181   /* store seqnum to drop flush events, they don't need to reach downstream */
6182   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6183   res = gst_pad_push_event (demux->sinkpad, event);
6184   demux->offset_seek_seqnum = 0;
6185
6186   return res;
6187 }
6188
6189 /* check for seekable upstream, above and beyond a mere query */
6190 static void
6191 gst_qtdemux_check_seekability (GstQTDemux * demux)
6192 {
6193   GstQuery *query;
6194   gboolean seekable = FALSE;
6195   gint64 start = -1, stop = -1;
6196
6197   if (demux->upstream_size)
6198     return;
6199
6200   if (demux->upstream_format_is_time)
6201     return;
6202
6203   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6204   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6205     GST_DEBUG_OBJECT (demux, "seeking query failed");
6206     goto done;
6207   }
6208
6209   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6210
6211   /* try harder to query upstream size if we didn't get it the first time */
6212   if (seekable && stop == -1) {
6213     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6214     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6215   }
6216
6217   /* if upstream doesn't know the size, it's likely that it's not seekable in
6218    * practice even if it technically may be seekable */
6219   if (seekable && (start != 0 || stop <= start)) {
6220     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6221     seekable = FALSE;
6222   }
6223
6224 done:
6225   gst_query_unref (query);
6226
6227   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6228       G_GUINT64_FORMAT ")", seekable, start, stop);
6229   demux->upstream_seekable = seekable;
6230   demux->upstream_size = seekable ? stop : -1;
6231 }
6232
6233 static void
6234 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6235 {
6236   g_return_if_fail (bytes <= demux->todrop);
6237
6238   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6239   gst_adapter_flush (demux->adapter, bytes);
6240   demux->neededbytes -= bytes;
6241   demux->offset += bytes;
6242   demux->todrop -= bytes;
6243 }
6244
6245 static void
6246 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6247 {
6248   if (G_UNLIKELY (demux->pending_newsegment)) {
6249     gint i;
6250
6251     gst_qtdemux_push_pending_newsegment (demux);
6252     /* clear to send tags on all streams */
6253     for (i = 0; i < demux->n_streams; i++) {
6254       QtDemuxStream *stream;
6255       stream = demux->streams[i];
6256       gst_qtdemux_push_tags (demux, stream);
6257       if (CUR_STREAM (stream)->sparse) {
6258         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6259         gst_pad_push_event (stream->pad,
6260             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6261       }
6262     }
6263   }
6264 }
6265
6266 static void
6267 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6268     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6269 {
6270   GstClockTime ts, dur;
6271   GstEvent *gap;
6272
6273   ts = pos;
6274   dur =
6275       stream->segments[segment_index].duration - (pos -
6276       stream->segments[segment_index].time);
6277   gap = gst_event_new_gap (ts, dur);
6278   stream->time_position += dur;
6279
6280   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6281       "segment: %" GST_PTR_FORMAT, gap);
6282   gst_pad_push_event (stream->pad, gap);
6283 }
6284
6285 static void
6286 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6287     QtDemuxStream * stream)
6288 {
6289   gint i;
6290
6291   /* Push any initial gap segments before proceeding to the
6292    * 'real' data */
6293   for (i = 0; i < stream->n_segments; i++) {
6294     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6295
6296     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6297       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6298           stream->time_position);
6299     } else {
6300       /* Only support empty segment at the beginning followed by
6301        * one non-empty segment, this was checked when parsing the
6302        * edts atom, arriving here is unexpected */
6303       g_assert (i + 1 == stream->n_segments);
6304       break;
6305     }
6306   }
6307 }
6308
6309 static GstFlowReturn
6310 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6311 {
6312   GstQTDemux *demux;
6313
6314   demux = GST_QTDEMUX (parent);
6315
6316   GST_DEBUG_OBJECT (demux,
6317       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6318       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6319       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6320       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6321       gst_buffer_get_size (inbuf), demux->offset);
6322
6323   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6324     gboolean is_gap_input = FALSE;
6325     gint i;
6326
6327     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6328
6329     for (i = 0; i < demux->n_streams; i++) {
6330       demux->streams[i]->discont = TRUE;
6331     }
6332
6333     /* Check if we can land back on our feet in the case where upstream is
6334      * handling the seeking/pushing of samples with gaps in between (like
6335      * in the case of trick-mode DASH for example) */
6336     if (demux->upstream_format_is_time
6337         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6338       gint i;
6339       for (i = 0; i < demux->n_streams; i++) {
6340         guint32 res;
6341         GST_LOG_OBJECT (demux,
6342             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6343             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6344         res =
6345             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6346             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6347         if (res != -1) {
6348           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6349           GST_LOG_OBJECT (demux,
6350               "Checking if sample %d from stream %d is valid (offset:%"
6351               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6352               sample->offset, sample->size);
6353           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6354             GST_LOG_OBJECT (demux,
6355                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6356                 res);
6357             is_gap_input = TRUE;
6358             /* We can go back to standard playback mode */
6359             demux->state = QTDEMUX_STATE_MOVIE;
6360             /* Remember which sample this stream is at */
6361             demux->streams[i]->sample_index = res;
6362             /* Finally update all push-based values to the expected values */
6363             demux->neededbytes = demux->streams[i]->samples[res].size;
6364             demux->offset = GST_BUFFER_OFFSET (inbuf);
6365             demux->mdatleft =
6366                 demux->mdatsize - demux->offset + demux->mdatoffset;
6367             demux->todrop = 0;
6368           }
6369         }
6370       }
6371       if (!is_gap_input) {
6372         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6373         /* Reset state if it's a real discont */
6374         demux->neededbytes = 16;
6375         demux->state = QTDEMUX_STATE_INITIAL;
6376         demux->offset = GST_BUFFER_OFFSET (inbuf);
6377         gst_adapter_clear (demux->adapter);
6378       }
6379     }
6380     /* Reverse fragmented playback, need to flush all we have before
6381      * consuming a new fragment.
6382      * The samples array have the timestamps calculated by accumulating the
6383      * durations but this won't work for reverse playback of fragments as
6384      * the timestamps of a subsequent fragment should be smaller than the
6385      * previously received one. */
6386     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6387       gst_qtdemux_process_adapter (demux, TRUE);
6388       for (i = 0; i < demux->n_streams; i++)
6389         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6390     }
6391   }
6392
6393   gst_adapter_push (demux->adapter, inbuf);
6394
6395   GST_DEBUG_OBJECT (demux,
6396       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6397       demux->neededbytes, gst_adapter_available (demux->adapter));
6398
6399   return gst_qtdemux_process_adapter (demux, FALSE);
6400 }
6401
6402 static GstFlowReturn
6403 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6404 {
6405   GstFlowReturn ret = GST_FLOW_OK;
6406
6407   /* we never really mean to buffer that much */
6408   if (demux->neededbytes == -1) {
6409     goto eos;
6410   }
6411
6412   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6413       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6414
6415 #ifndef GST_DISABLE_GST_DEBUG
6416     {
6417       guint64 discont_offset, distance_from_discont;
6418
6419       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6420       distance_from_discont =
6421           gst_adapter_distance_from_discont (demux->adapter);
6422
6423       GST_DEBUG_OBJECT (demux,
6424           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6425           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6426           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6427           demux->offset, discont_offset, distance_from_discont);
6428     }
6429 #endif
6430
6431     switch (demux->state) {
6432       case QTDEMUX_STATE_INITIAL:{
6433         const guint8 *data;
6434         guint32 fourcc;
6435         guint64 size;
6436
6437         gst_qtdemux_check_seekability (demux);
6438
6439         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6440
6441         /* get fourcc/length, set neededbytes */
6442         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6443             &size, &fourcc);
6444         gst_adapter_unmap (demux->adapter);
6445         data = NULL;
6446         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6447             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6448         if (size == 0) {
6449           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6450               (_("This file is invalid and cannot be played.")),
6451               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6452                   GST_FOURCC_ARGS (fourcc)));
6453           ret = GST_FLOW_ERROR;
6454           break;
6455         }
6456         if (fourcc == FOURCC_mdat) {
6457           gint next_entry = next_entry_size (demux);
6458           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6459             /* we have the headers, start playback */
6460             demux->state = QTDEMUX_STATE_MOVIE;
6461             demux->neededbytes = next_entry;
6462             demux->mdatleft = size;
6463             demux->mdatsize = demux->mdatleft;
6464           } else {
6465             /* no headers yet, try to get them */
6466             guint bs;
6467             gboolean res;
6468             guint64 old, target;
6469
6470           buffer_data:
6471             old = demux->offset;
6472             target = old + size;
6473
6474             /* try to jump over the atom with a seek */
6475             /* only bother if it seems worth doing so,
6476              * and avoids possible upstream/server problems */
6477             if (demux->upstream_seekable &&
6478                 demux->upstream_size > 4 * (1 << 20)) {
6479               res = qtdemux_seek_offset (demux, target);
6480             } else {
6481               GST_DEBUG_OBJECT (demux, "skipping seek");
6482               res = FALSE;
6483             }
6484
6485             if (res) {
6486               GST_DEBUG_OBJECT (demux, "seek success");
6487               /* remember the offset fo the first mdat so we can seek back to it
6488                * after we have the headers */
6489               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6490                 demux->first_mdat = old;
6491                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6492                     demux->first_mdat);
6493               }
6494               /* seek worked, continue reading */
6495               demux->offset = target;
6496               demux->neededbytes = 16;
6497               demux->state = QTDEMUX_STATE_INITIAL;
6498             } else {
6499               /* seek failed, need to buffer */
6500               demux->offset = old;
6501               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6502               /* there may be multiple mdat (or alike) buffers */
6503               /* sanity check */
6504               if (demux->mdatbuffer)
6505                 bs = gst_buffer_get_size (demux->mdatbuffer);
6506               else
6507                 bs = 0;
6508               if (size + bs > 10 * (1 << 20))
6509                 goto no_moov;
6510               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6511               demux->neededbytes = size;
6512               if (!demux->mdatbuffer)
6513                 demux->mdatoffset = demux->offset;
6514             }
6515           }
6516         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6517           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6518               (_("This file is invalid and cannot be played.")),
6519               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6520                   GST_FOURCC_ARGS (fourcc), size));
6521           ret = GST_FLOW_ERROR;
6522           break;
6523         } else {
6524           /* this means we already started buffering and still no moov header,
6525            * let's continue buffering everything till we get moov */
6526           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6527                   || fourcc == FOURCC_moof))
6528             goto buffer_data;
6529           demux->neededbytes = size;
6530           demux->state = QTDEMUX_STATE_HEADER;
6531         }
6532         break;
6533       }
6534       case QTDEMUX_STATE_HEADER:{
6535         const guint8 *data;
6536         guint32 fourcc;
6537
6538         GST_DEBUG_OBJECT (demux, "In header");
6539
6540         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6541
6542         /* parse the header */
6543         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6544             &fourcc);
6545         if (fourcc == FOURCC_moov) {
6546           gint n;
6547
6548           /* in usual fragmented setup we could try to scan for more
6549            * and end up at the the moov (after mdat) again */
6550           if (demux->got_moov && demux->n_streams > 0 &&
6551               (!demux->fragmented
6552                   || demux->last_moov_offset == demux->offset)) {
6553             GST_DEBUG_OBJECT (demux,
6554                 "Skipping moov atom as we have (this) one already");
6555           } else {
6556             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6557
6558             if (demux->got_moov && demux->fragmented) {
6559               GST_DEBUG_OBJECT (demux,
6560                   "Got a second moov, clean up data from old one");
6561               if (demux->moov_node_compressed) {
6562                 g_node_destroy (demux->moov_node_compressed);
6563                 if (demux->moov_node)
6564                   g_free (demux->moov_node->data);
6565               }
6566               demux->moov_node_compressed = NULL;
6567               if (demux->moov_node)
6568                 g_node_destroy (demux->moov_node);
6569               demux->moov_node = NULL;
6570             } else {
6571               /* prepare newsegment to send when streaming actually starts */
6572               if (!demux->pending_newsegment) {
6573                 demux->pending_newsegment =
6574                     gst_event_new_segment (&demux->segment);
6575                 if (demux->segment_seqnum)
6576                   gst_event_set_seqnum (demux->pending_newsegment,
6577                       demux->segment_seqnum);
6578               }
6579             }
6580
6581             demux->last_moov_offset = demux->offset;
6582
6583             qtdemux_parse_moov (demux, data, demux->neededbytes);
6584             qtdemux_node_dump (demux, demux->moov_node);
6585             qtdemux_parse_tree (demux);
6586             qtdemux_prepare_streams (demux);
6587             if (!demux->got_moov)
6588               qtdemux_expose_streams (demux);
6589             else {
6590
6591               for (n = 0; n < demux->n_streams; n++) {
6592                 QtDemuxStream *stream = demux->streams[n];
6593
6594                 gst_qtdemux_configure_stream (demux, stream);
6595               }
6596             }
6597
6598             demux->got_moov = TRUE;
6599             gst_qtdemux_check_send_pending_segment (demux);
6600
6601             /* fragmented streams headers shouldn't contain edts atoms */
6602             if (!demux->fragmented) {
6603               for (n = 0; n < demux->n_streams; n++) {
6604                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6605                     demux->streams[n]);
6606               }
6607             }
6608
6609             if (demux->moov_node_compressed) {
6610               g_node_destroy (demux->moov_node_compressed);
6611               g_free (demux->moov_node->data);
6612             }
6613             demux->moov_node_compressed = NULL;
6614             g_node_destroy (demux->moov_node);
6615             demux->moov_node = NULL;
6616             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6617           }
6618         } else if (fourcc == FOURCC_moof) {
6619           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6620             guint64 dist = 0;
6621             GstClockTime prev_pts;
6622             guint64 prev_offset;
6623             guint64 adapter_discont_offset, adapter_discont_dist;
6624
6625             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6626
6627             /*
6628              * The timestamp of the moof buffer is relevant as some scenarios
6629              * won't have the initial timestamp in the atoms. Whenever a new
6630              * buffer has started, we get that buffer's PTS and use it as a base
6631              * timestamp for the trun entries.
6632              *
6633              * To keep track of the current buffer timestamp and starting point
6634              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6635              * from the beggining of the buffer, with the distance and demux->offset
6636              * we know if it is still the same buffer or not.
6637              */
6638             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6639             prev_offset = demux->offset - dist;
6640             if (demux->fragment_start_offset == -1
6641                 || prev_offset > demux->fragment_start_offset) {
6642               demux->fragment_start_offset = prev_offset;
6643               demux->fragment_start = prev_pts;
6644               GST_DEBUG_OBJECT (demux,
6645                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6646                   GST_TIME_FORMAT, demux->fragment_start_offset,
6647                   GST_TIME_ARGS (demux->fragment_start));
6648             }
6649
6650             /* We can't use prev_offset() here because this would require
6651              * upstream to set consistent and correct offsets on all buffers
6652              * since the discont. Nothing ever did that in the past and we
6653              * would break backwards compatibility here then.
6654              * Instead take the offset we had at the last discont and count
6655              * the bytes from there. This works with old code as there would
6656              * be no discont between moov and moof, and also works with
6657              * adaptivedemux which correctly sets offset and will set the
6658              * DISCONT flag accordingly when needed.
6659              *
6660              * We also only do this for upstream TIME segments as otherwise
6661              * there are potential backwards compatibility problems with
6662              * seeking in PUSH mode and upstream providing inconsistent
6663              * timestamps. */
6664             adapter_discont_offset =
6665                 gst_adapter_offset_at_discont (demux->adapter);
6666             adapter_discont_dist =
6667                 gst_adapter_distance_from_discont (demux->adapter);
6668
6669             GST_DEBUG_OBJECT (demux,
6670                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6671                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6672                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6673
6674             if (demux->upstream_format_is_time) {
6675               demux->moof_offset = adapter_discont_offset;
6676               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6677                 demux->moof_offset += adapter_discont_dist;
6678               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6679                 demux->moof_offset = demux->offset;
6680             } else {
6681               demux->moof_offset = demux->offset;
6682             }
6683
6684             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6685                     demux->moof_offset, NULL)) {
6686               gst_adapter_unmap (demux->adapter);
6687               ret = GST_FLOW_ERROR;
6688               goto done;
6689             }
6690             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6691             if (demux->mss_mode && !demux->exposed) {
6692               if (!demux->pending_newsegment) {
6693                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6694                 demux->pending_newsegment =
6695                     gst_event_new_segment (&demux->segment);
6696                 if (demux->segment_seqnum)
6697                   gst_event_set_seqnum (demux->pending_newsegment,
6698                       demux->segment_seqnum);
6699               }
6700               qtdemux_expose_streams (demux);
6701             }
6702           } else {
6703             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6704           }
6705         } else if (fourcc == FOURCC_ftyp) {
6706           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6707           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6708         } else if (fourcc == FOURCC_uuid) {
6709           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6710           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6711         } else if (fourcc == FOURCC_sidx) {
6712           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6713           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6714         } else {
6715           switch (fourcc) {
6716             case FOURCC_styp:
6717               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6718                * FALLTHROUGH */
6719             case FOURCC_skip:
6720             case FOURCC_free:
6721               /* [free] and [skip] are padding atoms */
6722               GST_DEBUG_OBJECT (demux,
6723                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6724                   GST_FOURCC_ARGS (fourcc));
6725               break;
6726             default:
6727               GST_WARNING_OBJECT (demux,
6728                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6729                   GST_FOURCC_ARGS (fourcc));
6730               /* Let's jump that one and go back to initial state */
6731               break;
6732           }
6733         }
6734         gst_adapter_unmap (demux->adapter);
6735         data = NULL;
6736
6737         if (demux->mdatbuffer && demux->n_streams) {
6738           gsize remaining_data_size = 0;
6739
6740           /* the mdat was before the header */
6741           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6742               demux->n_streams, demux->mdatbuffer);
6743           /* restore our adapter/offset view of things with upstream;
6744            * put preceding buffered data ahead of current moov data.
6745            * This should also handle evil mdat, moov, mdat cases and alike */
6746           gst_adapter_flush (demux->adapter, demux->neededbytes);
6747
6748           /* Store any remaining data after the mdat for later usage */
6749           remaining_data_size = gst_adapter_available (demux->adapter);
6750           if (remaining_data_size > 0) {
6751             g_assert (demux->restoredata_buffer == NULL);
6752             demux->restoredata_buffer =
6753                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6754             demux->restoredata_offset = demux->offset + demux->neededbytes;
6755             GST_DEBUG_OBJECT (demux,
6756                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6757                 G_GUINT64_FORMAT, remaining_data_size,
6758                 demux->restoredata_offset);
6759           }
6760
6761           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6762           demux->mdatbuffer = NULL;
6763           demux->offset = demux->mdatoffset;
6764           demux->neededbytes = next_entry_size (demux);
6765           demux->state = QTDEMUX_STATE_MOVIE;
6766           demux->mdatleft = gst_adapter_available (demux->adapter);
6767           demux->mdatsize = demux->mdatleft;
6768         } else {
6769           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6770           gst_adapter_flush (demux->adapter, demux->neededbytes);
6771
6772           /* only go back to the mdat if there are samples to play */
6773           if (demux->got_moov && demux->first_mdat != -1
6774               && has_next_entry (demux)) {
6775             gboolean res;
6776
6777             /* we need to seek back */
6778             res = qtdemux_seek_offset (demux, demux->first_mdat);
6779             if (res) {
6780               demux->offset = demux->first_mdat;
6781             } else {
6782               GST_DEBUG_OBJECT (demux, "Seek back failed");
6783             }
6784           } else {
6785             demux->offset += demux->neededbytes;
6786           }
6787           demux->neededbytes = 16;
6788           demux->state = QTDEMUX_STATE_INITIAL;
6789         }
6790
6791         break;
6792       }
6793       case QTDEMUX_STATE_BUFFER_MDAT:{
6794         GstBuffer *buf;
6795         guint8 fourcc[4];
6796
6797         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6798             demux->offset);
6799         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6800         gst_buffer_extract (buf, 0, fourcc, 4);
6801         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6802             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6803         if (demux->mdatbuffer)
6804           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6805         else
6806           demux->mdatbuffer = buf;
6807         demux->offset += demux->neededbytes;
6808         demux->neededbytes = 16;
6809         demux->state = QTDEMUX_STATE_INITIAL;
6810         gst_qtdemux_post_progress (demux, 1, 1);
6811
6812         break;
6813       }
6814       case QTDEMUX_STATE_MOVIE:{
6815         QtDemuxStream *stream = NULL;
6816         QtDemuxSample *sample;
6817         int i = -1;
6818         GstClockTime dts, pts, duration;
6819         gboolean keyframe;
6820
6821         GST_DEBUG_OBJECT (demux,
6822             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6823
6824         if (demux->fragmented) {
6825           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6826               demux->mdatleft);
6827           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6828             /* if needed data starts within this atom,
6829              * then it should not exceed this atom */
6830             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6831               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6832                   (_("This file is invalid and cannot be played.")),
6833                   ("sample data crosses atom boundary"));
6834               ret = GST_FLOW_ERROR;
6835               break;
6836             }
6837             demux->mdatleft -= demux->neededbytes;
6838           } else {
6839             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6840             /* so we are dropping more than left in this atom */
6841             gst_qtdemux_drop_data (demux, demux->mdatleft);
6842             demux->mdatleft = 0;
6843
6844             /* need to resume atom parsing so we do not miss any other pieces */
6845             demux->state = QTDEMUX_STATE_INITIAL;
6846             demux->neededbytes = 16;
6847
6848             /* check if there was any stored post mdat data from previous buffers */
6849             if (demux->restoredata_buffer) {
6850               g_assert (gst_adapter_available (demux->adapter) == 0);
6851
6852               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6853               demux->restoredata_buffer = NULL;
6854               demux->offset = demux->restoredata_offset;
6855             }
6856
6857             break;
6858           }
6859         }
6860
6861         if (demux->todrop) {
6862           if (demux->cenc_aux_info_offset > 0) {
6863             GstByteReader br;
6864             const guint8 *data;
6865
6866             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6867             data = gst_adapter_map (demux->adapter, demux->todrop);
6868             gst_byte_reader_init (&br, data + 8, demux->todrop);
6869             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6870                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6871               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6872               ret = GST_FLOW_ERROR;
6873               gst_adapter_unmap (demux->adapter);
6874               g_free (demux->cenc_aux_info_sizes);
6875               demux->cenc_aux_info_sizes = NULL;
6876               goto done;
6877             }
6878             demux->cenc_aux_info_offset = 0;
6879             g_free (demux->cenc_aux_info_sizes);
6880             demux->cenc_aux_info_sizes = NULL;
6881             gst_adapter_unmap (demux->adapter);
6882           }
6883           gst_qtdemux_drop_data (demux, demux->todrop);
6884         }
6885
6886         /* first buffer? */
6887         /* initial newsegment sent here after having added pads,
6888          * possible others in sink_event */
6889         gst_qtdemux_check_send_pending_segment (demux);
6890
6891         /* Figure out which stream this packet belongs to */
6892         for (i = 0; i < demux->n_streams; i++) {
6893           stream = demux->streams[i];
6894           if (stream->sample_index >= stream->n_samples)
6895             continue;
6896           GST_LOG_OBJECT (demux,
6897               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6898               " / size:%d)", i, stream->sample_index,
6899               stream->samples[stream->sample_index].offset,
6900               stream->samples[stream->sample_index].size);
6901
6902           if (stream->samples[stream->sample_index].offset == demux->offset)
6903             break;
6904         }
6905
6906         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6907           goto unknown_stream;
6908
6909         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6910
6911         if (stream->new_caps) {
6912           gst_qtdemux_configure_stream (demux, stream);
6913         }
6914
6915         /* Put data in a buffer, set timestamps, caps, ... */
6916         sample = &stream->samples[stream->sample_index];
6917
6918         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6919           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6920               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6921
6922           dts = QTSAMPLE_DTS (stream, sample);
6923           pts = QTSAMPLE_PTS (stream, sample);
6924           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6925           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6926
6927           /* check for segment end */
6928           if (G_UNLIKELY (demux->segment.stop != -1
6929                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6930             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6931             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6932
6933             /* skip this data, stream is EOS */
6934             gst_adapter_flush (demux->adapter, demux->neededbytes);
6935             demux->offset += demux->neededbytes;
6936
6937             /* check if all streams are eos */
6938             ret = GST_FLOW_EOS;
6939             for (i = 0; i < demux->n_streams; i++) {
6940               if (!STREAM_IS_EOS (demux->streams[i])) {
6941                 ret = GST_FLOW_OK;
6942                 break;
6943               }
6944             }
6945           } else {
6946             GstBuffer *outbuf;
6947
6948             outbuf =
6949                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6950
6951             /* FIXME: should either be an assert or a plain check */
6952             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6953
6954             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6955                 dts, pts, duration, keyframe, dts, demux->offset);
6956           }
6957
6958           /* combine flows */
6959           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6960         } else {
6961           /* skip this data, stream is EOS */
6962           gst_adapter_flush (demux->adapter, demux->neededbytes);
6963         }
6964
6965         stream->sample_index++;
6966         stream->offset_in_sample = 0;
6967
6968         /* update current offset and figure out size of next buffer */
6969         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6970             demux->offset, demux->neededbytes);
6971         demux->offset += demux->neededbytes;
6972         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6973             demux->offset);
6974
6975
6976         if (ret == GST_FLOW_EOS) {
6977           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6978           demux->neededbytes = -1;
6979           goto eos;
6980         }
6981
6982         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6983           if (demux->fragmented) {
6984             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6985             /* there may be more to follow, only finish this atom */
6986             demux->todrop = demux->mdatleft;
6987             demux->neededbytes = demux->todrop;
6988             break;
6989           }
6990           goto eos;
6991         }
6992         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6993           goto non_ok_unlinked_flow;
6994         }
6995         break;
6996       }
6997       default:
6998         goto invalid_state;
6999     }
7000   }
7001
7002   /* when buffering movie data, at least show user something is happening */
7003   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7004       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7005     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7006         demux->neededbytes);
7007   }
7008 done:
7009
7010   return ret;
7011
7012   /* ERRORS */
7013 non_ok_unlinked_flow:
7014   {
7015     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7016         gst_flow_get_name (ret));
7017     return ret;
7018   }
7019 unknown_stream:
7020   {
7021     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7022     ret = GST_FLOW_ERROR;
7023     goto done;
7024   }
7025 eos:
7026   {
7027     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7028     ret = GST_FLOW_EOS;
7029     goto done;
7030   }
7031 invalid_state:
7032   {
7033     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7034         (NULL), ("qtdemuxer invalid state %d", demux->state));
7035     ret = GST_FLOW_ERROR;
7036     goto done;
7037   }
7038 no_moov:
7039   {
7040     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7041         (NULL), ("no 'moov' atom within the first 10 MB"));
7042     ret = GST_FLOW_ERROR;
7043     goto done;
7044   }
7045 }
7046
7047 static gboolean
7048 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7049 {
7050   GstQuery *query;
7051   gboolean pull_mode;
7052
7053   query = gst_query_new_scheduling ();
7054
7055   if (!gst_pad_peer_query (sinkpad, query)) {
7056     gst_query_unref (query);
7057     goto activate_push;
7058   }
7059
7060   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7061       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7062   gst_query_unref (query);
7063
7064   if (!pull_mode)
7065     goto activate_push;
7066
7067   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7068   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7069
7070 activate_push:
7071   {
7072     GST_DEBUG_OBJECT (sinkpad, "activating push");
7073     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7074   }
7075 }
7076
7077 static gboolean
7078 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7079     GstPadMode mode, gboolean active)
7080 {
7081   gboolean res;
7082   GstQTDemux *demux = GST_QTDEMUX (parent);
7083
7084   switch (mode) {
7085     case GST_PAD_MODE_PUSH:
7086       demux->pullbased = FALSE;
7087       res = TRUE;
7088       break;
7089     case GST_PAD_MODE_PULL:
7090       if (active) {
7091         demux->pullbased = TRUE;
7092         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7093             sinkpad, NULL);
7094       } else {
7095         res = gst_pad_stop_task (sinkpad);
7096       }
7097       break;
7098     default:
7099       res = FALSE;
7100       break;
7101   }
7102   return res;
7103 }
7104
7105 #ifdef HAVE_ZLIB
7106 static void *
7107 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7108 {
7109   guint8 *buffer;
7110   z_stream z;
7111   int ret;
7112
7113   memset (&z, 0, sizeof (z));
7114   z.zalloc = NULL;
7115   z.zfree = NULL;
7116   z.opaque = NULL;
7117
7118   if ((ret = inflateInit (&z)) != Z_OK) {
7119     GST_ERROR ("inflateInit() returned %d", ret);
7120     return NULL;
7121   }
7122
7123   z.next_in = z_buffer;
7124   z.avail_in = z_length;
7125
7126   buffer = (guint8 *) g_malloc (*length);
7127   z.avail_out = *length;
7128   z.next_out = (Bytef *) buffer;
7129   do {
7130     ret = inflate (&z, Z_NO_FLUSH);
7131     if (ret == Z_STREAM_END) {
7132       break;
7133     } else if (ret != Z_OK) {
7134       GST_WARNING ("inflate() returned %d", ret);
7135       break;
7136     }
7137
7138     *length += 4096;
7139     buffer = (guint8 *) g_realloc (buffer, *length);
7140     z.next_out = (Bytef *) (buffer + z.total_out);
7141     z.avail_out += 4096;
7142   } while (z.avail_in > 0);
7143
7144   if (ret != Z_STREAM_END) {
7145     g_free (buffer);
7146     buffer = NULL;
7147     *length = 0;
7148   } else {
7149     *length = z.total_out;
7150   }
7151
7152   inflateEnd (&z);
7153
7154   return buffer;
7155 }
7156 #endif /* HAVE_ZLIB */
7157
7158 static gboolean
7159 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7160 {
7161   GNode *cmov;
7162
7163   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7164
7165   /* counts as header data */
7166   qtdemux->header_size += length;
7167
7168   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7169   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7170
7171   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7172   if (cmov) {
7173     guint32 method;
7174     GNode *dcom;
7175     GNode *cmvd;
7176     guint32 dcom_len;
7177
7178     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7179     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7180     if (dcom == NULL || cmvd == NULL)
7181       goto invalid_compression;
7182
7183     dcom_len = QT_UINT32 (dcom->data);
7184     if (dcom_len < 12)
7185       goto invalid_compression;
7186
7187     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7188     switch (method) {
7189 #ifdef HAVE_ZLIB
7190       case FOURCC_zlib:{
7191         guint uncompressed_length;
7192         guint compressed_length;
7193         guint8 *buf;
7194         guint32 cmvd_len;
7195
7196         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7197         if (cmvd_len < 12)
7198           goto invalid_compression;
7199
7200         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7201         compressed_length = cmvd_len - 12;
7202         GST_LOG ("length = %u", uncompressed_length);
7203
7204         buf =
7205             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7206             compressed_length, &uncompressed_length);
7207
7208         if (buf) {
7209           qtdemux->moov_node_compressed = qtdemux->moov_node;
7210           qtdemux->moov_node = g_node_new (buf);
7211
7212           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7213               uncompressed_length);
7214         }
7215         break;
7216       }
7217 #endif /* HAVE_ZLIB */
7218       default:
7219         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7220             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7221         break;
7222     }
7223   }
7224   return TRUE;
7225
7226   /* ERRORS */
7227 invalid_compression:
7228   {
7229     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7230     return FALSE;
7231   }
7232 }
7233
7234 static gboolean
7235 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7236     const guint8 * end)
7237 {
7238   while (G_UNLIKELY (buf < end)) {
7239     GNode *child;
7240     guint32 len;
7241
7242     if (G_UNLIKELY (buf + 4 > end)) {
7243       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7244       break;
7245     }
7246     len = QT_UINT32 (buf);
7247     if (G_UNLIKELY (len == 0)) {
7248       GST_LOG_OBJECT (qtdemux, "empty container");
7249       break;
7250     }
7251     if (G_UNLIKELY (len < 8)) {
7252       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7253       break;
7254     }
7255     if (G_UNLIKELY (len > (end - buf))) {
7256       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7257           (gint) (end - buf));
7258       break;
7259     }
7260
7261     child = g_node_new ((guint8 *) buf);
7262     g_node_append (node, child);
7263     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7264     qtdemux_parse_node (qtdemux, child, buf, len);
7265
7266     buf += len;
7267   }
7268   return TRUE;
7269 }
7270
7271 static gboolean
7272 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7273     GNode * xdxt)
7274 {
7275   int len = QT_UINT32 (xdxt->data);
7276   guint8 *buf = xdxt->data;
7277   guint8 *end = buf + len;
7278   GstBuffer *buffer;
7279
7280   /* skip size and type */
7281   buf += 8;
7282   end -= 8;
7283
7284   while (buf < end) {
7285     gint size;
7286     guint32 type;
7287
7288     size = QT_UINT32 (buf);
7289     type = QT_FOURCC (buf + 4);
7290
7291     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7292
7293     if (buf + size > end || size <= 0)
7294       break;
7295
7296     buf += 8;
7297     size -= 8;
7298
7299     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7300         GST_FOURCC_ARGS (type));
7301
7302     switch (type) {
7303       case FOURCC_tCtH:
7304         buffer = gst_buffer_new_and_alloc (size);
7305         gst_buffer_fill (buffer, 0, buf, size);
7306         stream->buffers = g_slist_append (stream->buffers, buffer);
7307         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7308         break;
7309       case FOURCC_tCt_:
7310         buffer = gst_buffer_new_and_alloc (size);
7311         gst_buffer_fill (buffer, 0, buf, size);
7312         stream->buffers = g_slist_append (stream->buffers, buffer);
7313         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7314         break;
7315       case FOURCC_tCtC:
7316         buffer = gst_buffer_new_and_alloc (size);
7317         gst_buffer_fill (buffer, 0, buf, size);
7318         stream->buffers = g_slist_append (stream->buffers, buffer);
7319         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7320         break;
7321       default:
7322         GST_WARNING_OBJECT (qtdemux,
7323             "unknown theora cookie %" GST_FOURCC_FORMAT,
7324             GST_FOURCC_ARGS (type));
7325         break;
7326     }
7327     buf += size;
7328   }
7329   return TRUE;
7330 }
7331
7332 static gboolean
7333 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7334     guint length)
7335 {
7336   guint32 fourcc = 0;
7337   guint32 node_length = 0;
7338   const QtNodeType *type;
7339   const guint8 *end;
7340
7341   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7342
7343   if (G_UNLIKELY (length < 8))
7344     goto not_enough_data;
7345
7346   node_length = QT_UINT32 (buffer);
7347   fourcc = QT_FOURCC (buffer + 4);
7348
7349   /* ignore empty nodes */
7350   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7351     return TRUE;
7352
7353   type = qtdemux_type_get (fourcc);
7354
7355   end = buffer + length;
7356
7357   GST_LOG_OBJECT (qtdemux,
7358       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7359       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7360
7361   if (node_length > length)
7362     goto broken_atom_size;
7363
7364   if (type->flags & QT_FLAG_CONTAINER) {
7365     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7366   } else {
7367     switch (fourcc) {
7368       case FOURCC_stsd:
7369       {
7370         if (node_length < 20) {
7371           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7372           break;
7373         }
7374         GST_DEBUG_OBJECT (qtdemux,
7375             "parsing stsd (sample table, sample description) atom");
7376         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7377         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7378         break;
7379       }
7380       case FOURCC_mp4a:
7381       case FOURCC_alac:
7382       case FOURCC_fLaC:
7383       {
7384         guint32 version;
7385         guint32 offset;
7386         guint min_size;
7387
7388         /* also read alac (or whatever) in stead of mp4a in the following,
7389          * since a similar layout is used in other cases as well */
7390         if (fourcc == FOURCC_mp4a)
7391           min_size = 20;
7392         else if (fourcc == FOURCC_fLaC)
7393           min_size = 86;
7394         else
7395           min_size = 40;
7396
7397         /* There are two things we might encounter here: a true mp4a atom, and
7398            an mp4a entry in an stsd atom. The latter is what we're interested
7399            in, and it looks like an atom, but isn't really one. The true mp4a
7400            atom is short, so we detect it based on length here. */
7401         if (length < min_size) {
7402           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7403               GST_FOURCC_ARGS (fourcc));
7404           break;
7405         }
7406
7407         /* 'version' here is the sound sample description version. Types 0 and
7408            1 are documented in the QTFF reference, but type 2 is not: it's
7409            described in Apple header files instead (struct SoundDescriptionV2
7410            in Movies.h) */
7411         version = QT_UINT16 (buffer + 16);
7412
7413         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7414             GST_FOURCC_ARGS (fourcc), version);
7415
7416         /* parse any esds descriptors */
7417         switch (version) {
7418           case 0:
7419             offset = 0x24;
7420             break;
7421           case 1:
7422             offset = 0x34;
7423             break;
7424           case 2:
7425             offset = 0x48;
7426             break;
7427           default:
7428             GST_WARNING_OBJECT (qtdemux,
7429                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7430                 GST_FOURCC_ARGS (fourcc), version);
7431             offset = 0;
7432             break;
7433         }
7434         if (offset)
7435           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7436         break;
7437       }
7438       case FOURCC_mp4v:
7439       case FOURCC_MP4V:
7440       case FOURCC_fmp4:
7441       case FOURCC_FMP4:
7442       case FOURCC_apcs:
7443       case FOURCC_apch:
7444       case FOURCC_apcn:
7445       case FOURCC_apco:
7446       case FOURCC_ap4h:
7447       case FOURCC_xvid:
7448       case FOURCC_XVID:
7449       case FOURCC_H264:
7450       case FOURCC_avc1:
7451       case FOURCC_avc3:
7452       case FOURCC_H265:
7453       case FOURCC_hvc1:
7454       case FOURCC_hev1:
7455       case FOURCC_mjp2:
7456       case FOURCC_encv:
7457       {
7458         guint32 version;
7459         guint32 str_len;
7460
7461         /* codec_data is contained inside these atoms, which all have
7462          * the same format. */
7463         /* video sample description size is 86 bytes without extension.
7464          * node_length have to be bigger than 86 bytes because video sample
7465          * description can include extenstions such as esds, fiel, glbl, etc. */
7466         if (node_length < 86) {
7467           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7468               " sample description length too short (%u < 86)",
7469               GST_FOURCC_ARGS (fourcc), node_length);
7470           break;
7471         }
7472
7473         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7474             GST_FOURCC_ARGS (fourcc));
7475
7476         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7477          *              its data format.
7478          * revision level (2 bytes) : must be set to 0. */
7479         version = QT_UINT32 (buffer + 16);
7480         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7481
7482         /* compressor name : PASCAL string and informative purposes
7483          * first byte : the number of bytes to be displayed.
7484          *              it has to be less than 32 because it is reserved
7485          *              space of 32 bytes total including itself. */
7486         str_len = QT_UINT8 (buffer + 50);
7487         if (str_len < 32)
7488           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7489               (char *) buffer + 51);
7490         else
7491           GST_WARNING_OBJECT (qtdemux,
7492               "compressorname length too big (%u > 31)", str_len);
7493
7494         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7495             end - buffer);
7496         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7497         break;
7498       }
7499       case FOURCC_meta:
7500       {
7501         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7502         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7503         break;
7504       }
7505       case FOURCC_mp4s:
7506       {
7507         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7508         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7509         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7510         break;
7511       }
7512       case FOURCC_XiTh:
7513       {
7514         guint32 version;
7515         guint32 offset;
7516
7517         if (length < 16) {
7518           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7519               GST_FOURCC_ARGS (fourcc));
7520           break;
7521         }
7522
7523         version = QT_UINT32 (buffer + 12);
7524         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7525
7526         switch (version) {
7527           case 0x00000001:
7528             offset = 0x62;
7529             break;
7530           default:
7531             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7532             offset = 0;
7533             break;
7534         }
7535         if (offset) {
7536           if (length < offset) {
7537             GST_WARNING_OBJECT (qtdemux,
7538                 "skipping too small %" GST_FOURCC_FORMAT " box",
7539                 GST_FOURCC_ARGS (fourcc));
7540             break;
7541           }
7542           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7543         }
7544         break;
7545       }
7546       case FOURCC_in24:
7547       {
7548         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7549         break;
7550       }
7551       case FOURCC_uuid:
7552       {
7553         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7554         break;
7555       }
7556       case FOURCC_enca:
7557       {
7558         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7559         break;
7560       }
7561       default:
7562         if (!strcmp (type->name, "unknown"))
7563           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7564         break;
7565     }
7566   }
7567   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7568       GST_FOURCC_ARGS (fourcc));
7569   return TRUE;
7570
7571 /* ERRORS */
7572 not_enough_data:
7573   {
7574     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7575         (_("This file is corrupt and cannot be played.")),
7576         ("Not enough data for an atom header, got only %u bytes", length));
7577     return FALSE;
7578   }
7579 broken_atom_size:
7580   {
7581     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7582         (_("This file is corrupt and cannot be played.")),
7583         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7584             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7585             length));
7586     return FALSE;
7587   }
7588 }
7589
7590 static GNode *
7591 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7592 {
7593   GNode *child;
7594   guint8 *buffer;
7595   guint32 child_fourcc;
7596
7597   for (child = g_node_first_child (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 (G_UNLIKELY (child_fourcc == fourcc)) {
7604       return child;
7605     }
7606   }
7607   return NULL;
7608 }
7609
7610 static GNode *
7611 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7612     GstByteReader * parser)
7613 {
7614   GNode *child;
7615   guint8 *buffer;
7616   guint32 child_fourcc, child_len;
7617
7618   for (child = g_node_first_child (node); child;
7619       child = g_node_next_sibling (child)) {
7620     buffer = (guint8 *) child->data;
7621
7622     child_len = QT_UINT32 (buffer);
7623     child_fourcc = QT_FOURCC (buffer + 4);
7624
7625     if (G_UNLIKELY (child_fourcc == fourcc)) {
7626       if (G_UNLIKELY (child_len < (4 + 4)))
7627         return NULL;
7628       /* FIXME: must verify if atom length < parent atom length */
7629       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7630       return child;
7631     }
7632   }
7633   return NULL;
7634 }
7635
7636 static GNode *
7637 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7638 {
7639   return g_node_nth_child (node, index);
7640 }
7641
7642 static GNode *
7643 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7644     GstByteReader * parser)
7645 {
7646   GNode *child;
7647   guint8 *buffer;
7648   guint32 child_fourcc, child_len;
7649
7650   for (child = g_node_next_sibling (node); child;
7651       child = g_node_next_sibling (child)) {
7652     buffer = (guint8 *) child->data;
7653
7654     child_fourcc = QT_FOURCC (buffer + 4);
7655
7656     if (child_fourcc == fourcc) {
7657       if (parser) {
7658         child_len = QT_UINT32 (buffer);
7659         if (G_UNLIKELY (child_len < (4 + 4)))
7660           return NULL;
7661         /* FIXME: must verify if atom length < parent atom length */
7662         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7663       }
7664       return child;
7665     }
7666   }
7667   return NULL;
7668 }
7669
7670 static GNode *
7671 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7672 {
7673   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7674 }
7675
7676 static void
7677 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7678 {
7679 /* FIXME: This can only reliably work if demuxers have a
7680  * separate streaming thread per srcpad. This should be
7681  * done in a demuxer base class, which integrates parts
7682  * of multiqueue
7683  *
7684  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7685  */
7686 #if 0
7687   GstQuery *query;
7688
7689   query = gst_query_new_allocation (stream->caps, FALSE);
7690
7691   if (!gst_pad_peer_query (stream->pad, query)) {
7692     /* not a problem, just debug a little */
7693     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7694   }
7695
7696   if (stream->allocator)
7697     gst_object_unref (stream->allocator);
7698
7699   if (gst_query_get_n_allocation_params (query) > 0) {
7700     /* try the allocator */
7701     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7702         &stream->params);
7703     stream->use_allocator = TRUE;
7704   } else {
7705     stream->allocator = NULL;
7706     gst_allocation_params_init (&stream->params);
7707     stream->use_allocator = FALSE;
7708   }
7709   gst_query_unref (query);
7710 #endif
7711 }
7712
7713 static gboolean
7714 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7715     QtDemuxStream * stream)
7716 {
7717   GstStructure *s;
7718   const gchar *selected_system;
7719
7720   g_return_val_if_fail (qtdemux != NULL, FALSE);
7721   g_return_val_if_fail (stream != NULL, FALSE);
7722   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7723       FALSE);
7724
7725   if (stream->protection_scheme_type != FOURCC_cenc) {
7726     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7727     return FALSE;
7728   }
7729   if (qtdemux->protection_system_ids == NULL) {
7730     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7731         "cenc protection system information has been found");
7732     return FALSE;
7733   }
7734   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7735   selected_system = gst_protection_select_system ((const gchar **)
7736       qtdemux->protection_system_ids->pdata);
7737   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7738       qtdemux->protection_system_ids->len - 1);
7739   if (!selected_system) {
7740     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7741         "suitable decryptor element has been found");
7742     return FALSE;
7743   }
7744
7745   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7746   if (!gst_structure_has_name (s, "application/x-cenc")) {
7747     gst_structure_set (s,
7748         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7749         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7750         NULL);
7751     gst_structure_set_name (s, "application/x-cenc");
7752   }
7753   return TRUE;
7754 }
7755
7756 static gboolean
7757 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7758 {
7759   if (stream->subtype == FOURCC_vide) {
7760     /* fps is calculated base on the duration of the average framerate since
7761      * qt does not have a fixed framerate. */
7762     gboolean fps_available = TRUE;
7763
7764     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7765       /* still frame */
7766       CUR_STREAM (stream)->fps_n = 0;
7767       CUR_STREAM (stream)->fps_d = 1;
7768     } else {
7769       if (stream->duration == 0 || stream->n_samples < 2) {
7770         CUR_STREAM (stream)->fps_n = stream->timescale;
7771         CUR_STREAM (stream)->fps_d = 1;
7772         fps_available = FALSE;
7773       } else {
7774         GstClockTime avg_duration;
7775         guint64 duration;
7776         guint32 n_samples;
7777
7778         /* duration and n_samples can be updated for fragmented format
7779          * so, framerate of fragmented format is calculated using data in a moof */
7780         if (qtdemux->fragmented && stream->n_samples_moof > 0
7781             && stream->duration_moof > 0) {
7782           n_samples = stream->n_samples_moof;
7783           duration = stream->duration_moof;
7784         } else {
7785           n_samples = stream->n_samples;
7786           duration = stream->duration;
7787         }
7788
7789         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7790         /* stream->duration is guint64, timescale, n_samples are guint32 */
7791         avg_duration =
7792             gst_util_uint64_scale_round (duration -
7793             stream->first_duration, GST_SECOND,
7794             (guint64) (stream->timescale) * (n_samples - 1));
7795
7796         GST_LOG_OBJECT (qtdemux,
7797             "Calculating avg sample duration based on stream (or moof) duration %"
7798             G_GUINT64_FORMAT
7799             " minus first sample %u, leaving %d samples gives %"
7800             GST_TIME_FORMAT, duration, stream->first_duration,
7801             n_samples - 1, GST_TIME_ARGS (avg_duration));
7802
7803         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7804             &CUR_STREAM (stream)->fps_d);
7805
7806         GST_DEBUG_OBJECT (qtdemux,
7807             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7808             stream->timescale, CUR_STREAM (stream)->fps_n,
7809             CUR_STREAM (stream)->fps_d);
7810       }
7811     }
7812
7813     if (CUR_STREAM (stream)->caps) {
7814       CUR_STREAM (stream)->caps =
7815           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7816
7817       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7818           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7819           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7820
7821       /* set framerate if calculated framerate is reliable */
7822       if (fps_available) {
7823         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7824             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7825             CUR_STREAM (stream)->fps_d, NULL);
7826       }
7827
7828       /* calculate pixel-aspect-ratio using display width and height */
7829       GST_DEBUG_OBJECT (qtdemux,
7830           "video size %dx%d, target display size %dx%d",
7831           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7832           stream->display_width, stream->display_height);
7833       /* qt file might have pasp atom */
7834       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7835         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7836             CUR_STREAM (stream)->par_h);
7837         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7838             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7839             CUR_STREAM (stream)->par_h, NULL);
7840       } else if (stream->display_width > 0 && stream->display_height > 0
7841           && CUR_STREAM (stream)->width > 0
7842           && CUR_STREAM (stream)->height > 0) {
7843         gint n, d;
7844
7845         /* calculate the pixel aspect ratio using the display and pixel w/h */
7846         n = stream->display_width * CUR_STREAM (stream)->height;
7847         d = stream->display_height * CUR_STREAM (stream)->width;
7848         if (n == d)
7849           n = d = 1;
7850         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7851         CUR_STREAM (stream)->par_w = n;
7852         CUR_STREAM (stream)->par_h = d;
7853         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7854             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7855             CUR_STREAM (stream)->par_h, NULL);
7856       }
7857
7858       if (CUR_STREAM (stream)->interlace_mode > 0) {
7859         if (CUR_STREAM (stream)->interlace_mode == 1) {
7860           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7861               G_TYPE_STRING, "progressive", NULL);
7862         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7863           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7864               G_TYPE_STRING, "interleaved", NULL);
7865           if (CUR_STREAM (stream)->field_order == 9) {
7866             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7867                 G_TYPE_STRING, "top-field-first", NULL);
7868           } else if (CUR_STREAM (stream)->field_order == 14) {
7869             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7870                 G_TYPE_STRING, "bottom-field-first", NULL);
7871           }
7872         }
7873       }
7874
7875       /* Create incomplete colorimetry here if needed */
7876       if (CUR_STREAM (stream)->colorimetry.range ||
7877           CUR_STREAM (stream)->colorimetry.matrix ||
7878           CUR_STREAM (stream)->colorimetry.transfer
7879           || CUR_STREAM (stream)->colorimetry.primaries) {
7880         gchar *colorimetry =
7881             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7882         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7883             G_TYPE_STRING, colorimetry, NULL);
7884         g_free (colorimetry);
7885       }
7886
7887       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7888         guint par_w = 1, par_h = 1;
7889
7890         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7891           par_w = CUR_STREAM (stream)->par_w;
7892           par_h = CUR_STREAM (stream)->par_h;
7893         }
7894
7895         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7896                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7897                 par_h)) {
7898           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7899         }
7900
7901         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7902             "multiview-mode", G_TYPE_STRING,
7903             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7904             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7905             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7906       }
7907     }
7908   }
7909
7910   else if (stream->subtype == FOURCC_soun) {
7911     if (CUR_STREAM (stream)->caps) {
7912       CUR_STREAM (stream)->caps =
7913           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7914       if (CUR_STREAM (stream)->rate > 0)
7915         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7916             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7917       if (CUR_STREAM (stream)->n_channels > 0)
7918         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7919             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7920       if (CUR_STREAM (stream)->n_channels > 2) {
7921         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7922          * correctly; this is just the minimum we can do - assume
7923          * we don't actually have any channel positions. */
7924         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7925             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7926       }
7927     }
7928   }
7929
7930   if (stream->pad) {
7931     GstCaps *prev_caps = NULL;
7932
7933     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7934     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7935     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7936     gst_pad_set_active (stream->pad, TRUE);
7937
7938     gst_pad_use_fixed_caps (stream->pad);
7939
7940     if (stream->protected) {
7941       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7942         GST_ERROR_OBJECT (qtdemux,
7943             "Failed to configure protected stream caps.");
7944         return FALSE;
7945       }
7946     }
7947
7948     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7949         CUR_STREAM (stream)->caps);
7950     if (stream->new_stream) {
7951       gchar *stream_id;
7952       GstEvent *event;
7953       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7954
7955       event =
7956           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7957           0);
7958       if (event) {
7959         gst_event_parse_stream_flags (event, &stream_flags);
7960         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7961           qtdemux->have_group_id = TRUE;
7962         else
7963           qtdemux->have_group_id = FALSE;
7964         gst_event_unref (event);
7965       } else if (!qtdemux->have_group_id) {
7966         qtdemux->have_group_id = TRUE;
7967         qtdemux->group_id = gst_util_group_id_next ();
7968       }
7969
7970       stream->new_stream = FALSE;
7971       stream_id =
7972           gst_pad_create_stream_id_printf (stream->pad,
7973           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7974       event = gst_event_new_stream_start (stream_id);
7975       if (qtdemux->have_group_id)
7976         gst_event_set_group_id (event, qtdemux->group_id);
7977       if (stream->disabled)
7978         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7979       if (CUR_STREAM (stream)->sparse) {
7980         stream_flags |= GST_STREAM_FLAG_SPARSE;
7981       } else {
7982         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7983       }
7984       gst_event_set_stream_flags (event, stream_flags);
7985       gst_pad_push_event (stream->pad, event);
7986       g_free (stream_id);
7987     }
7988
7989     prev_caps = gst_pad_get_current_caps (stream->pad);
7990
7991     if (CUR_STREAM (stream)->caps) {
7992       if (!prev_caps
7993           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
7994         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7995             CUR_STREAM (stream)->caps);
7996         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
7997       } else {
7998         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7999       }
8000     } else {
8001       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8002     }
8003
8004     if (prev_caps)
8005       gst_caps_unref (prev_caps);
8006     stream->new_caps = FALSE;
8007   }
8008   return TRUE;
8009 }
8010
8011 static void
8012 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8013     QtDemuxStream * stream)
8014 {
8015   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8016     return;
8017
8018   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8019       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8020   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8021           stream->stsd_entries_length)) {
8022     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8023         (_("This file is invalid and cannot be played.")),
8024         ("New sample description id is out of bounds (%d >= %d)",
8025             stream->stsd_sample_description_id, stream->stsd_entries_length));
8026   } else {
8027     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8028     stream->new_caps = TRUE;
8029   }
8030 }
8031
8032 static gboolean
8033 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8034     QtDemuxStream * stream, GstTagList * list)
8035 {
8036   gboolean ret = TRUE;
8037   /* consistent default for push based mode */
8038   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8039
8040   if (stream->subtype == FOURCC_vide) {
8041     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8042
8043     stream->pad =
8044         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8045     g_free (name);
8046
8047     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8048       gst_object_unref (stream->pad);
8049       stream->pad = NULL;
8050       ret = FALSE;
8051       goto done;
8052     }
8053
8054     qtdemux->n_video_streams++;
8055   } else if (stream->subtype == FOURCC_soun) {
8056     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8057
8058     stream->pad =
8059         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8060     g_free (name);
8061     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8062       gst_object_unref (stream->pad);
8063       stream->pad = NULL;
8064       ret = FALSE;
8065       goto done;
8066     }
8067     qtdemux->n_audio_streams++;
8068   } else if (stream->subtype == FOURCC_strm) {
8069     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8070   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8071       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8072     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8073
8074     stream->pad =
8075         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8076     g_free (name);
8077     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8078       gst_object_unref (stream->pad);
8079       stream->pad = NULL;
8080       ret = FALSE;
8081       goto done;
8082     }
8083     qtdemux->n_sub_streams++;
8084   } else if (CUR_STREAM (stream)->caps) {
8085     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8086
8087     stream->pad =
8088         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8089     g_free (name);
8090     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8091       gst_object_unref (stream->pad);
8092       stream->pad = NULL;
8093       ret = FALSE;
8094       goto done;
8095     }
8096     qtdemux->n_video_streams++;
8097   } else {
8098     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8099     goto done;
8100   }
8101
8102   if (stream->pad) {
8103     GList *l;
8104
8105     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8106         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8107     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8108     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8109
8110     if (stream->stream_tags)
8111       gst_tag_list_unref (stream->stream_tags);
8112     stream->stream_tags = list;
8113     list = NULL;
8114     /* global tags go on each pad anyway */
8115     stream->send_global_tags = TRUE;
8116     /* send upstream GST_EVENT_PROTECTION events that were received before
8117        this source pad was created */
8118     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8119       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8120   }
8121 done:
8122   if (list)
8123     gst_tag_list_unref (list);
8124   return ret;
8125 }
8126
8127 /* find next atom with @fourcc starting at @offset */
8128 static GstFlowReturn
8129 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8130     guint64 * length, guint32 fourcc)
8131 {
8132   GstFlowReturn ret;
8133   guint32 lfourcc;
8134   GstBuffer *buf;
8135
8136   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8137       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8138
8139   while (TRUE) {
8140     GstMapInfo map;
8141
8142     buf = NULL;
8143     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8144     if (G_UNLIKELY (ret != GST_FLOW_OK))
8145       goto locate_failed;
8146     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8147       /* likely EOF */
8148       ret = GST_FLOW_EOS;
8149       gst_buffer_unref (buf);
8150       goto locate_failed;
8151     }
8152     gst_buffer_map (buf, &map, GST_MAP_READ);
8153     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8154     gst_buffer_unmap (buf, &map);
8155     gst_buffer_unref (buf);
8156
8157     if (G_UNLIKELY (*length == 0)) {
8158       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8159       ret = GST_FLOW_ERROR;
8160       goto locate_failed;
8161     }
8162
8163     if (lfourcc == fourcc) {
8164       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8165           *offset);
8166       break;
8167     } else {
8168       GST_LOG_OBJECT (qtdemux,
8169           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8170           GST_FOURCC_ARGS (fourcc), *offset);
8171       *offset += *length;
8172     }
8173   }
8174
8175   return GST_FLOW_OK;
8176
8177 locate_failed:
8178   {
8179     /* might simply have had last one */
8180     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8181     return ret;
8182   }
8183 }
8184
8185 /* should only do something in pull mode */
8186 /* call with OBJECT lock */
8187 static GstFlowReturn
8188 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8189 {
8190   guint64 length, offset;
8191   GstBuffer *buf = NULL;
8192   GstFlowReturn ret = GST_FLOW_OK;
8193   GstFlowReturn res = GST_FLOW_OK;
8194   GstMapInfo map;
8195
8196   offset = qtdemux->moof_offset;
8197   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8198
8199   if (!offset) {
8200     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8201     return GST_FLOW_EOS;
8202   }
8203
8204   /* best not do pull etc with lock held */
8205   GST_OBJECT_UNLOCK (qtdemux);
8206
8207   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8208   if (ret != GST_FLOW_OK)
8209     goto flow_failed;
8210
8211   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8212   if (G_UNLIKELY (ret != GST_FLOW_OK))
8213     goto flow_failed;
8214   gst_buffer_map (buf, &map, GST_MAP_READ);
8215   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8216     gst_buffer_unmap (buf, &map);
8217     gst_buffer_unref (buf);
8218     buf = NULL;
8219     goto parse_failed;
8220   }
8221
8222   gst_buffer_unmap (buf, &map);
8223   gst_buffer_unref (buf);
8224   buf = NULL;
8225
8226   offset += length;
8227   /* look for next moof */
8228   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8229   if (G_UNLIKELY (ret != GST_FLOW_OK))
8230     goto flow_failed;
8231
8232 exit:
8233   GST_OBJECT_LOCK (qtdemux);
8234
8235   qtdemux->moof_offset = offset;
8236
8237   return res;
8238
8239 parse_failed:
8240   {
8241     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8242     offset = 0;
8243     res = GST_FLOW_ERROR;
8244     goto exit;
8245   }
8246 flow_failed:
8247   {
8248     /* maybe upstream temporarily flushing */
8249     if (ret != GST_FLOW_FLUSHING) {
8250       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8251       offset = 0;
8252     } else {
8253       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8254       /* resume at current position next time */
8255     }
8256     res = ret;
8257     goto exit;
8258   }
8259 }
8260
8261 /* initialise bytereaders for stbl sub-atoms */
8262 static gboolean
8263 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8264 {
8265   stream->stbl_index = -1;      /* no samples have yet been parsed */
8266   stream->sample_index = -1;
8267
8268   /* time-to-sample atom */
8269   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8270     goto corrupt_file;
8271
8272   /* copy atom data into a new buffer for later use */
8273   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8274
8275   /* skip version + flags */
8276   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8277       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8278     goto corrupt_file;
8279   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8280
8281   /* make sure there's enough data */
8282   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8283     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8284     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8285         stream->n_sample_times);
8286     if (!stream->n_sample_times)
8287       goto corrupt_file;
8288   }
8289
8290   /* sync sample atom */
8291   stream->stps_present = FALSE;
8292   if ((stream->stss_present =
8293           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8294               &stream->stss) ? TRUE : FALSE) == TRUE) {
8295     /* copy atom data into a new buffer for later use */
8296     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8297
8298     /* skip version + flags */
8299     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8300         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8301       goto corrupt_file;
8302
8303     if (stream->n_sample_syncs) {
8304       /* make sure there's enough data */
8305       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8306         goto corrupt_file;
8307     }
8308
8309     /* partial sync sample atom */
8310     if ((stream->stps_present =
8311             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8312                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8313       /* copy atom data into a new buffer for later use */
8314       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8315
8316       /* skip version + flags */
8317       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8318           !gst_byte_reader_get_uint32_be (&stream->stps,
8319               &stream->n_sample_partial_syncs))
8320         goto corrupt_file;
8321
8322       /* if there are no entries, the stss table contains the real
8323        * sync samples */
8324       if (stream->n_sample_partial_syncs) {
8325         /* make sure there's enough data */
8326         if (!qt_atom_parser_has_chunks (&stream->stps,
8327                 stream->n_sample_partial_syncs, 4))
8328           goto corrupt_file;
8329       }
8330     }
8331   }
8332
8333   /* sample size */
8334   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8335     goto no_samples;
8336
8337   /* copy atom data into a new buffer for later use */
8338   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8339
8340   /* skip version + flags */
8341   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8342       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8343     goto corrupt_file;
8344
8345   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8346     goto corrupt_file;
8347
8348   if (!stream->n_samples)
8349     goto no_samples;
8350
8351   /* sample-to-chunk atom */
8352   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8353     goto corrupt_file;
8354
8355   /* copy atom data into a new buffer for later use */
8356   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8357
8358   /* skip version + flags */
8359   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8360       !gst_byte_reader_get_uint32_be (&stream->stsc,
8361           &stream->n_samples_per_chunk))
8362     goto corrupt_file;
8363
8364   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8365       stream->n_samples_per_chunk);
8366
8367   /* make sure there's enough data */
8368   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8369           12))
8370     goto corrupt_file;
8371
8372
8373   /* chunk offset */
8374   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8375     stream->co_size = sizeof (guint32);
8376   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8377           &stream->stco))
8378     stream->co_size = sizeof (guint64);
8379   else
8380     goto corrupt_file;
8381
8382   /* copy atom data into a new buffer for later use */
8383   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8384
8385   /* skip version + flags */
8386   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8387     goto corrupt_file;
8388
8389   /* chunks_are_samples == TRUE means treat chunks as samples */
8390   stream->chunks_are_samples = stream->sample_size
8391       && !CUR_STREAM (stream)->sampled;
8392   if (stream->chunks_are_samples) {
8393     /* treat chunks as samples */
8394     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8395       goto corrupt_file;
8396   } else {
8397     /* skip number of entries */
8398     if (!gst_byte_reader_skip (&stream->stco, 4))
8399       goto corrupt_file;
8400
8401     /* make sure there are enough data in the stsz atom */
8402     if (!stream->sample_size) {
8403       /* different sizes for each sample */
8404       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8405         goto corrupt_file;
8406     }
8407   }
8408
8409   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8410       stream->n_samples, (guint) sizeof (QtDemuxSample),
8411       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8412
8413   if (stream->n_samples >=
8414       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8415     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8416         "be larger than %uMB (broken file?)", stream->n_samples,
8417         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8418     return FALSE;
8419   }
8420
8421   g_assert (stream->samples == NULL);
8422   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8423   if (!stream->samples) {
8424     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8425         stream->n_samples);
8426     return FALSE;
8427   }
8428
8429   /* composition time-to-sample */
8430   if ((stream->ctts_present =
8431           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8432               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8433     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8434
8435     /* copy atom data into a new buffer for later use */
8436     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8437
8438     /* skip version + flags */
8439     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8440         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8441             &stream->n_composition_times))
8442       goto corrupt_file;
8443
8444     /* make sure there's enough data */
8445     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8446             4 + 4))
8447       goto corrupt_file;
8448
8449     /* This is optional, if missing we iterate the ctts */
8450     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8451       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8452           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8453         g_free ((gpointer) cslg.data);
8454         goto corrupt_file;
8455       }
8456     } else {
8457       gint32 cslg_least = 0;
8458       guint num_entries, pos;
8459       gint i;
8460
8461       pos = gst_byte_reader_get_pos (&stream->ctts);
8462       num_entries = stream->n_composition_times;
8463
8464       stream->cslg_shift = 0;
8465
8466       for (i = 0; i < num_entries; i++) {
8467         gint32 offset;
8468
8469         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8470         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8471
8472         if (offset < cslg_least)
8473           cslg_least = offset;
8474       }
8475
8476       if (cslg_least < 0)
8477         stream->cslg_shift = ABS (cslg_least);
8478       else
8479         stream->cslg_shift = 0;
8480
8481       /* reset the reader so we can generate sample table */
8482       gst_byte_reader_set_pos (&stream->ctts, pos);
8483     }
8484   } else {
8485     /* Ensure the cslg_shift value is consistent so we can use it
8486      * unconditionnally to produce TS and Segment */
8487     stream->cslg_shift = 0;
8488   }
8489
8490   return TRUE;
8491
8492 corrupt_file:
8493   {
8494     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8495         (_("This file is corrupt and cannot be played.")), (NULL));
8496     return FALSE;
8497   }
8498 no_samples:
8499   {
8500     gst_qtdemux_stbl_free (stream);
8501     if (!qtdemux->fragmented) {
8502       /* not quite good */
8503       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8504       return FALSE;
8505     } else {
8506       /* may pick up samples elsewhere */
8507       return TRUE;
8508     }
8509   }
8510 }
8511
8512 /* collect samples from the next sample to be parsed up to sample @n for @stream
8513  * by reading the info from @stbl
8514  *
8515  * This code can be executed from both the streaming thread and the seeking
8516  * thread so it takes the object lock to protect itself
8517  */
8518 static gboolean
8519 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8520 {
8521   gint i, j, k;
8522   QtDemuxSample *samples, *first, *cur, *last;
8523   guint32 n_samples_per_chunk;
8524   guint32 n_samples;
8525
8526   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8527       GST_FOURCC_FORMAT ", pad %s",
8528       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8529       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8530
8531   n_samples = stream->n_samples;
8532
8533   if (n >= n_samples)
8534     goto out_of_samples;
8535
8536   GST_OBJECT_LOCK (qtdemux);
8537   if (n <= stream->stbl_index)
8538     goto already_parsed;
8539
8540   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8541
8542   if (!stream->stsz.data) {
8543     /* so we already parsed and passed all the moov samples;
8544      * onto fragmented ones */
8545     g_assert (qtdemux->fragmented);
8546     goto done;
8547   }
8548
8549   /* pointer to the sample table */
8550   samples = stream->samples;
8551
8552   /* starts from -1, moves to the next sample index to parse */
8553   stream->stbl_index++;
8554
8555   /* keep track of the first and last sample to fill */
8556   first = &samples[stream->stbl_index];
8557   last = &samples[n];
8558
8559   if (!stream->chunks_are_samples) {
8560     /* set the sample sizes */
8561     if (stream->sample_size == 0) {
8562       /* different sizes for each sample */
8563       for (cur = first; cur <= last; cur++) {
8564         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8565         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8566             (guint) (cur - samples), cur->size);
8567       }
8568     } else {
8569       /* samples have the same size */
8570       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8571       for (cur = first; cur <= last; cur++)
8572         cur->size = stream->sample_size;
8573     }
8574   }
8575
8576   n_samples_per_chunk = stream->n_samples_per_chunk;
8577   cur = first;
8578
8579   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8580     guint32 last_chunk;
8581
8582     if (stream->stsc_chunk_index >= stream->last_chunk
8583         || stream->stsc_chunk_index < stream->first_chunk) {
8584       stream->first_chunk =
8585           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8586       stream->samples_per_chunk =
8587           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8588       /* starts from 1 */
8589       stream->stsd_sample_description_id =
8590           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8591
8592       /* chunk numbers are counted from 1 it seems */
8593       if (G_UNLIKELY (stream->first_chunk == 0))
8594         goto corrupt_file;
8595
8596       --stream->first_chunk;
8597
8598       /* the last chunk of each entry is calculated by taking the first chunk
8599        * of the next entry; except if there is no next, where we fake it with
8600        * INT_MAX */
8601       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8602         stream->last_chunk = G_MAXUINT32;
8603       } else {
8604         stream->last_chunk =
8605             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8606         if (G_UNLIKELY (stream->last_chunk == 0))
8607           goto corrupt_file;
8608
8609         --stream->last_chunk;
8610       }
8611
8612       GST_LOG_OBJECT (qtdemux,
8613           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8614           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8615           stream->samples_per_chunk, stream->stsd_sample_description_id);
8616
8617       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8618         goto corrupt_file;
8619
8620       if (stream->last_chunk != G_MAXUINT32) {
8621         if (!qt_atom_parser_peek_sub (&stream->stco,
8622                 stream->first_chunk * stream->co_size,
8623                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8624                 &stream->co_chunk))
8625           goto corrupt_file;
8626
8627       } else {
8628         stream->co_chunk = stream->stco;
8629         if (!gst_byte_reader_skip (&stream->co_chunk,
8630                 stream->first_chunk * stream->co_size))
8631           goto corrupt_file;
8632       }
8633
8634       stream->stsc_chunk_index = stream->first_chunk;
8635     }
8636
8637     last_chunk = stream->last_chunk;
8638
8639     if (stream->chunks_are_samples) {
8640       cur = &samples[stream->stsc_chunk_index];
8641
8642       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8643         if (j > n) {
8644           /* save state */
8645           stream->stsc_chunk_index = j;
8646           goto done;
8647         }
8648
8649         cur->offset =
8650             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8651             stream->co_size);
8652
8653         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8654             "%" G_GUINT64_FORMAT, j, cur->offset);
8655
8656         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8657             CUR_STREAM (stream)->bytes_per_frame > 0) {
8658           cur->size =
8659               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8660               CUR_STREAM (stream)->samples_per_frame *
8661               CUR_STREAM (stream)->bytes_per_frame;
8662         } else {
8663           cur->size = stream->samples_per_chunk;
8664         }
8665
8666         GST_DEBUG_OBJECT (qtdemux,
8667             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8668             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8669                     stream->stco_sample_index)), cur->size);
8670
8671         cur->timestamp = stream->stco_sample_index;
8672         cur->duration = stream->samples_per_chunk;
8673         cur->keyframe = TRUE;
8674         cur++;
8675
8676         stream->stco_sample_index += stream->samples_per_chunk;
8677       }
8678       stream->stsc_chunk_index = j;
8679     } else {
8680       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8681         guint32 samples_per_chunk;
8682         guint64 chunk_offset;
8683
8684         if (!stream->stsc_sample_index
8685             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8686                 &stream->chunk_offset))
8687           goto corrupt_file;
8688
8689         samples_per_chunk = stream->samples_per_chunk;
8690         chunk_offset = stream->chunk_offset;
8691
8692         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8693           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8694               G_GUINT64_FORMAT " and size %d",
8695               (guint) (cur - samples), chunk_offset, cur->size);
8696
8697           cur->offset = chunk_offset;
8698           chunk_offset += cur->size;
8699           cur++;
8700
8701           if (G_UNLIKELY (cur > last)) {
8702             /* save state */
8703             stream->stsc_sample_index = k + 1;
8704             stream->chunk_offset = chunk_offset;
8705             stream->stsc_chunk_index = j;
8706             goto done2;
8707           }
8708         }
8709         stream->stsc_sample_index = 0;
8710       }
8711       stream->stsc_chunk_index = j;
8712     }
8713     stream->stsc_index++;
8714   }
8715
8716   if (stream->chunks_are_samples)
8717     goto ctts;
8718 done2:
8719   {
8720     guint32 n_sample_times;
8721
8722     n_sample_times = stream->n_sample_times;
8723     cur = first;
8724
8725     for (i = stream->stts_index; i < n_sample_times; i++) {
8726       guint32 stts_samples;
8727       gint32 stts_duration;
8728       gint64 stts_time;
8729
8730       if (stream->stts_sample_index >= stream->stts_samples
8731           || !stream->stts_sample_index) {
8732
8733         stream->stts_samples =
8734             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8735         stream->stts_duration =
8736             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8737
8738         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8739             i, stream->stts_samples, stream->stts_duration);
8740
8741         stream->stts_sample_index = 0;
8742       }
8743
8744       stts_samples = stream->stts_samples;
8745       stts_duration = stream->stts_duration;
8746       stts_time = stream->stts_time;
8747
8748       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8749         GST_DEBUG_OBJECT (qtdemux,
8750             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8751             (guint) (cur - samples), j,
8752             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8753
8754         cur->timestamp = stts_time;
8755         cur->duration = stts_duration;
8756
8757         /* avoid 32-bit wrap-around,
8758          * but still mind possible 'negative' duration */
8759         stts_time += (gint64) stts_duration;
8760         cur++;
8761
8762         if (G_UNLIKELY (cur > last)) {
8763           /* save values */
8764           stream->stts_time = stts_time;
8765           stream->stts_sample_index = j + 1;
8766           if (stream->stts_sample_index >= stream->stts_samples)
8767             stream->stts_index++;
8768           goto done3;
8769         }
8770       }
8771       stream->stts_sample_index = 0;
8772       stream->stts_time = stts_time;
8773       stream->stts_index++;
8774     }
8775     /* fill up empty timestamps with the last timestamp, this can happen when
8776      * the last samples do not decode and so we don't have timestamps for them.
8777      * We however look at the last timestamp to estimate the track length so we
8778      * need something in here. */
8779     for (; cur < last; cur++) {
8780       GST_DEBUG_OBJECT (qtdemux,
8781           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8782           (guint) (cur - samples),
8783           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8784       cur->timestamp = stream->stts_time;
8785       cur->duration = -1;
8786     }
8787   }
8788 done3:
8789   {
8790     /* sample sync, can be NULL */
8791     if (stream->stss_present == TRUE) {
8792       guint32 n_sample_syncs;
8793
8794       n_sample_syncs = stream->n_sample_syncs;
8795
8796       if (!n_sample_syncs) {
8797         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8798         stream->all_keyframe = TRUE;
8799       } else {
8800         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8801           /* note that the first sample is index 1, not 0 */
8802           guint32 index;
8803
8804           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8805
8806           if (G_LIKELY (index > 0 && index <= n_samples)) {
8807             index -= 1;
8808             samples[index].keyframe = TRUE;
8809             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8810             /* and exit if we have enough samples */
8811             if (G_UNLIKELY (index >= n)) {
8812               i++;
8813               break;
8814             }
8815           }
8816         }
8817         /* save state */
8818         stream->stss_index = i;
8819       }
8820
8821       /* stps marks partial sync frames like open GOP I-Frames */
8822       if (stream->stps_present == TRUE) {
8823         guint32 n_sample_partial_syncs;
8824
8825         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8826
8827         /* if there are no entries, the stss table contains the real
8828          * sync samples */
8829         if (n_sample_partial_syncs) {
8830           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8831             /* note that the first sample is index 1, not 0 */
8832             guint32 index;
8833
8834             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8835
8836             if (G_LIKELY (index > 0 && index <= n_samples)) {
8837               index -= 1;
8838               samples[index].keyframe = TRUE;
8839               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8840               /* and exit if we have enough samples */
8841               if (G_UNLIKELY (index >= n)) {
8842                 i++;
8843                 break;
8844               }
8845             }
8846           }
8847           /* save state */
8848           stream->stps_index = i;
8849         }
8850       }
8851     } else {
8852       /* no stss, all samples are keyframes */
8853       stream->all_keyframe = TRUE;
8854       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8855     }
8856   }
8857
8858 ctts:
8859   /* composition time to sample */
8860   if (stream->ctts_present == TRUE) {
8861     guint32 n_composition_times;
8862     guint32 ctts_count;
8863     gint32 ctts_soffset;
8864
8865     /* Fill in the pts_offsets */
8866     cur = first;
8867     n_composition_times = stream->n_composition_times;
8868
8869     for (i = stream->ctts_index; i < n_composition_times; i++) {
8870       if (stream->ctts_sample_index >= stream->ctts_count
8871           || !stream->ctts_sample_index) {
8872         stream->ctts_count =
8873             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8874         stream->ctts_soffset =
8875             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8876         stream->ctts_sample_index = 0;
8877       }
8878
8879       ctts_count = stream->ctts_count;
8880       ctts_soffset = stream->ctts_soffset;
8881
8882       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8883         cur->pts_offset = ctts_soffset;
8884         cur++;
8885
8886         if (G_UNLIKELY (cur > last)) {
8887           /* save state */
8888           stream->ctts_sample_index = j + 1;
8889           goto done;
8890         }
8891       }
8892       stream->ctts_sample_index = 0;
8893       stream->ctts_index++;
8894     }
8895   }
8896 done:
8897   stream->stbl_index = n;
8898   /* if index has been completely parsed, free data that is no-longer needed */
8899   if (n + 1 == stream->n_samples) {
8900     gst_qtdemux_stbl_free (stream);
8901     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8902     if (qtdemux->pullbased) {
8903       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8904       while (n + 1 == stream->n_samples)
8905         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8906           break;
8907     }
8908   }
8909   GST_OBJECT_UNLOCK (qtdemux);
8910
8911   return TRUE;
8912
8913   /* SUCCESS */
8914 already_parsed:
8915   {
8916     GST_LOG_OBJECT (qtdemux,
8917         "Tried to parse up to sample %u but this sample has already been parsed",
8918         n);
8919     /* if fragmented, there may be more */
8920     if (qtdemux->fragmented && n == stream->stbl_index)
8921       goto done;
8922     GST_OBJECT_UNLOCK (qtdemux);
8923     return TRUE;
8924   }
8925   /* ERRORS */
8926 out_of_samples:
8927   {
8928     GST_LOG_OBJECT (qtdemux,
8929         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8930         stream->n_samples);
8931     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8932         (_("This file is corrupt and cannot be played.")), (NULL));
8933     return FALSE;
8934   }
8935 corrupt_file:
8936   {
8937     GST_OBJECT_UNLOCK (qtdemux);
8938     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8939         (_("This file is corrupt and cannot be played.")), (NULL));
8940     return FALSE;
8941   }
8942 }
8943
8944 /* collect all segment info for @stream.
8945  */
8946 static gboolean
8947 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8948     GNode * trak)
8949 {
8950   GNode *edts;
8951   /* accept edts if they contain gaps at start and there is only
8952    * one media segment */
8953   gboolean allow_pushbased_edts = TRUE;
8954   gint media_segments_count = 0;
8955
8956   /* parse and prepare segment info from the edit list */
8957   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8958   stream->n_segments = 0;
8959   stream->segments = NULL;
8960   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8961     GNode *elst;
8962     gint n_segments;
8963     gint i, count, entry_size;
8964     guint64 time;
8965     GstClockTime stime;
8966     const guint8 *buffer;
8967     guint8 version;
8968     guint32 size;
8969
8970     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8971     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8972       goto done;
8973
8974     buffer = elst->data;
8975
8976     size = QT_UINT32 (buffer);
8977     /* version, flags, n_segments */
8978     if (size < 16) {
8979       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8980       goto done;
8981     }
8982     version = QT_UINT8 (buffer + 8);
8983     entry_size = (version == 1) ? 20 : 12;
8984
8985     n_segments = QT_UINT32 (buffer + 12);
8986
8987     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8988       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8989       goto done;
8990     }
8991
8992     /* we might allocate a bit too much, at least allocate 1 segment */
8993     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8994
8995     /* segments always start from 0 */
8996     time = 0;
8997     stime = 0;
8998     count = 0;
8999     buffer += 16;
9000     for (i = 0; i < n_segments; i++) {
9001       guint64 duration;
9002       guint64 media_time;
9003       gboolean time_valid = TRUE;
9004       QtDemuxSegment *segment;
9005       guint32 rate_int;
9006       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9007
9008       if (version == 1) {
9009         media_time = QT_UINT64 (buffer + 8);
9010         duration = QT_UINT64 (buffer);
9011         if (media_time == G_MAXUINT64)
9012           time_valid = FALSE;
9013       } else {
9014         media_time = QT_UINT32 (buffer + 4);
9015         duration = QT_UINT32 (buffer);
9016         if (media_time == G_MAXUINT32)
9017           time_valid = FALSE;
9018       }
9019
9020       if (time_valid)
9021         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9022
9023       segment = &stream->segments[count++];
9024
9025       /* time and duration expressed in global timescale */
9026       segment->time = stime;
9027       /* add non scaled values so we don't cause roundoff errors */
9028       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9029         time += duration;
9030         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9031         segment->duration = stime - segment->time;
9032       } else {
9033         /* zero duration does not imply media_start == media_stop
9034          * but, only specify media_start.*/
9035         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9036         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9037             && stime >= media_start) {
9038           segment->duration = stime - media_start;
9039         } else {
9040           segment->duration = GST_CLOCK_TIME_NONE;
9041         }
9042       }
9043       segment->stop_time = stime;
9044
9045       segment->trak_media_start = media_time;
9046       /* media_time expressed in stream timescale */
9047       if (time_valid) {
9048         segment->media_start = media_start;
9049         segment->media_stop = segment->media_start + segment->duration;
9050         media_segments_count++;
9051       } else {
9052         segment->media_start = GST_CLOCK_TIME_NONE;
9053         segment->media_stop = GST_CLOCK_TIME_NONE;
9054       }
9055       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9056
9057       if (rate_int <= 1) {
9058         /* 0 is not allowed, some programs write 1 instead of the floating point
9059          * value */
9060         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9061             rate_int);
9062         segment->rate = 1;
9063       } else {
9064         segment->rate = rate_int / 65536.0;
9065       }
9066
9067       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9068           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9069           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9070           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9071           i, GST_TIME_ARGS (segment->time),
9072           GST_TIME_ARGS (segment->duration),
9073           GST_TIME_ARGS (segment->media_start), media_time,
9074           GST_TIME_ARGS (segment->media_stop),
9075           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9076           stream->timescale);
9077       if (segment->stop_time > qtdemux->segment.stop) {
9078         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9079             " extends to %" GST_TIME_FORMAT
9080             " past the end of the file duration %" GST_TIME_FORMAT
9081             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9082             GST_TIME_ARGS (qtdemux->segment.stop));
9083         qtdemux->segment.stop = segment->stop_time;
9084       }
9085
9086       buffer += entry_size;
9087     }
9088     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9089     stream->n_segments = count;
9090     if (media_segments_count != 1)
9091       allow_pushbased_edts = FALSE;
9092   }
9093 done:
9094
9095   /* push based does not handle segments, so act accordingly here,
9096    * and warn if applicable */
9097   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9098     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9099     /* remove and use default one below, we stream like it anyway */
9100     g_free (stream->segments);
9101     stream->segments = NULL;
9102     stream->n_segments = 0;
9103   }
9104
9105   /* no segments, create one to play the complete trak */
9106   if (stream->n_segments == 0) {
9107     GstClockTime stream_duration =
9108         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9109
9110     if (stream->segments == NULL)
9111       stream->segments = g_new (QtDemuxSegment, 1);
9112
9113     /* represent unknown our way */
9114     if (stream_duration == 0)
9115       stream_duration = GST_CLOCK_TIME_NONE;
9116
9117     stream->segments[0].time = 0;
9118     stream->segments[0].stop_time = stream_duration;
9119     stream->segments[0].duration = stream_duration;
9120     stream->segments[0].media_start = 0;
9121     stream->segments[0].media_stop = stream_duration;
9122     stream->segments[0].rate = 1.0;
9123     stream->segments[0].trak_media_start = 0;
9124
9125     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9126         GST_TIME_ARGS (stream_duration));
9127     stream->n_segments = 1;
9128     stream->dummy_segment = TRUE;
9129   }
9130   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9131
9132   return TRUE;
9133 }
9134
9135 /*
9136  * Parses the stsd atom of a svq3 trak looking for
9137  * the SMI and gama atoms.
9138  */
9139 static void
9140 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9141     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9142 {
9143   const guint8 *_gamma = NULL;
9144   GstBuffer *_seqh = NULL;
9145   const guint8 *stsd_data = stsd_entry_data;
9146   guint32 length = QT_UINT32 (stsd_data);
9147   guint16 version;
9148
9149   if (length < 32) {
9150     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9151     goto end;
9152   }
9153
9154   stsd_data += 16;
9155   length -= 16;
9156   version = QT_UINT16 (stsd_data);
9157   if (version == 3) {
9158     if (length >= 70) {
9159       length -= 70;
9160       stsd_data += 70;
9161       while (length > 8) {
9162         guint32 fourcc, size;
9163         const guint8 *data;
9164         size = QT_UINT32 (stsd_data);
9165         fourcc = QT_FOURCC (stsd_data + 4);
9166         data = stsd_data + 8;
9167
9168         if (size == 0) {
9169           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9170               "svq3 atom parsing");
9171           goto end;
9172         }
9173
9174         switch (fourcc) {
9175           case FOURCC_gama:{
9176             if (size == 12) {
9177               _gamma = data;
9178             } else {
9179               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9180                   " for gama atom, expected 12", size);
9181             }
9182             break;
9183           }
9184           case FOURCC_SMI_:{
9185             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9186               guint32 seqh_size;
9187               if (_seqh != NULL) {
9188                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9189                     " found, ignoring");
9190               } else {
9191                 seqh_size = QT_UINT32 (data + 4);
9192                 if (seqh_size > 0) {
9193                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9194                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9195                 }
9196               }
9197             }
9198             break;
9199           }
9200           default:{
9201             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9202                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9203           }
9204         }
9205
9206         if (size <= length) {
9207           length -= size;
9208           stsd_data += size;
9209         }
9210       }
9211     } else {
9212       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9213     }
9214   } else {
9215     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9216         G_GUINT16_FORMAT, version);
9217     goto end;
9218   }
9219
9220 end:
9221   if (gamma) {
9222     *gamma = _gamma;
9223   }
9224   if (seqh) {
9225     *seqh = _seqh;
9226   } else if (_seqh) {
9227     gst_buffer_unref (_seqh);
9228   }
9229 }
9230
9231 static gchar *
9232 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9233 {
9234   GNode *dinf;
9235   GstByteReader dref;
9236   gchar *uri = NULL;
9237
9238   /*
9239    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9240    * atom that might contain a 'data' atom with the rtsp uri.
9241    * This case was reported in bug #597497, some info about
9242    * the hndl atom can be found in TN1195
9243    */
9244   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9245   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9246
9247   if (dinf) {
9248     guint32 dref_num_entries = 0;
9249     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9250         gst_byte_reader_skip (&dref, 4) &&
9251         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9252       gint i;
9253
9254       /* search dref entries for hndl atom */
9255       for (i = 0; i < dref_num_entries; i++) {
9256         guint32 size = 0, type;
9257         guint8 string_len = 0;
9258         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9259             qt_atom_parser_get_fourcc (&dref, &type)) {
9260           if (type == FOURCC_hndl) {
9261             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9262
9263             /* skip data reference handle bytes and the
9264              * following pascal string and some extra 4
9265              * bytes I have no idea what are */
9266             if (!gst_byte_reader_skip (&dref, 4) ||
9267                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9268                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9269               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9270               break;
9271             }
9272
9273             /* iterate over the atoms to find the data atom */
9274             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9275               guint32 atom_size;
9276               guint32 atom_type;
9277
9278               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9279                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9280                 if (atom_type == FOURCC_data) {
9281                   const guint8 *uri_aux = NULL;
9282
9283                   /* found the data atom that might contain the rtsp uri */
9284                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9285                       "hndl atom, interpreting it as an URI");
9286                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9287                           &uri_aux)) {
9288                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9289                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9290                     else
9291                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9292                           "didn't contain a rtsp address");
9293                   } else {
9294                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9295                         "atom contents");
9296                   }
9297                   break;
9298                 }
9299                 /* skipping to the next entry */
9300                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9301                   break;
9302               } else {
9303                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9304                     "atom header");
9305                 break;
9306               }
9307             }
9308             break;
9309           }
9310           /* skip to the next entry */
9311           if (!gst_byte_reader_skip (&dref, size - 8))
9312             break;
9313         } else {
9314           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9315         }
9316       }
9317       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9318     }
9319   }
9320   return uri;
9321 }
9322
9323 #define AMR_NB_ALL_MODES        0x81ff
9324 #define AMR_WB_ALL_MODES        0x83ff
9325 static guint
9326 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9327 {
9328   /* The 'damr' atom is of the form:
9329    *
9330    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9331    *    32 b       8 b          16 b           8 b                 8 b
9332    *
9333    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9334    * represents the highest mode used in the stream (and thus the maximum
9335    * bitrate), with a couple of special cases as seen below.
9336    */
9337
9338   /* Map of frame type ID -> bitrate */
9339   static const guint nb_bitrates[] = {
9340     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9341   };
9342   static const guint wb_bitrates[] = {
9343     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9344   };
9345   GstMapInfo map;
9346   gsize max_mode;
9347   guint16 mode_set;
9348
9349   gst_buffer_map (buf, &map, GST_MAP_READ);
9350
9351   if (map.size != 0x11) {
9352     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9353     goto bad_data;
9354   }
9355
9356   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9357     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9358         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9359     goto bad_data;
9360   }
9361
9362   mode_set = QT_UINT16 (map.data + 13);
9363
9364   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9365     max_mode = 7 + (wb ? 1 : 0);
9366   else
9367     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9368     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9369
9370   if (max_mode == -1) {
9371     GST_DEBUG ("No mode indication was found (mode set) = %x",
9372         (guint) mode_set);
9373     goto bad_data;
9374   }
9375
9376   gst_buffer_unmap (buf, &map);
9377   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9378
9379 bad_data:
9380   gst_buffer_unmap (buf, &map);
9381   return 0;
9382 }
9383
9384 static gboolean
9385 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9386     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9387 {
9388   /*
9389    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9390    * [0 1 2]
9391    * [3 4 5]
9392    * [6 7 8]
9393    */
9394
9395   if (gst_byte_reader_get_remaining (reader) < 36)
9396     return FALSE;
9397
9398   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9399   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9400   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9401   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9402   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9403   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9404   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9405   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9406   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9407
9408   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9409   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9410       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9411       matrix[2] & 0xFF);
9412   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9413       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9414       matrix[5] & 0xFF);
9415   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9416       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9417       matrix[8] & 0xFF);
9418
9419   return TRUE;
9420 }
9421
9422 static void
9423 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9424     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9425 {
9426
9427 /* [a b c]
9428  * [d e f]
9429  * [g h i]
9430  *
9431  * This macro will only compare value abdegh, it expects cfi to have already
9432  * been checked
9433  */
9434 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9435                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9436
9437   /* only handle the cases where the last column has standard values */
9438   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9439     const gchar *rotation_tag = NULL;
9440
9441     /* no rotation needed */
9442     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9443       /* NOP */
9444     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9445       rotation_tag = "rotate-90";
9446     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9447       rotation_tag = "rotate-180";
9448     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9449       rotation_tag = "rotate-270";
9450     } else {
9451       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9452     }
9453
9454     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9455         rotation_tag);
9456     if (rotation_tag != NULL) {
9457       if (*taglist == NULL)
9458         *taglist = gst_tag_list_new_empty ();
9459       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9460           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9461     }
9462   } else {
9463     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9464   }
9465 }
9466
9467 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9468  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9469  * Common Encryption (cenc), the function will also parse the tenc box (defined
9470  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9471  * (typically an enc[v|a|t|s] sample entry); the function will set
9472  * @original_fmt to the fourcc of the original unencrypted stream format.
9473  * Returns TRUE if successful; FALSE otherwise. */
9474 static gboolean
9475 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9476     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9477 {
9478   GNode *sinf;
9479   GNode *frma;
9480   GNode *schm;
9481   GNode *schi;
9482
9483   g_return_val_if_fail (qtdemux != NULL, FALSE);
9484   g_return_val_if_fail (stream != NULL, FALSE);
9485   g_return_val_if_fail (container != NULL, FALSE);
9486   g_return_val_if_fail (original_fmt != NULL, FALSE);
9487
9488   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9489   if (G_UNLIKELY (!sinf)) {
9490     if (stream->protection_scheme_type == FOURCC_cenc) {
9491       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9492           "mandatory for Common Encryption");
9493       return FALSE;
9494     }
9495     return TRUE;
9496   }
9497
9498   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9499   if (G_UNLIKELY (!frma)) {
9500     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9501     return FALSE;
9502   }
9503
9504   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9505   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9506       GST_FOURCC_ARGS (*original_fmt));
9507
9508   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9509   if (!schm) {
9510     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9511     return FALSE;
9512   }
9513   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9514   stream->protection_scheme_version =
9515       QT_UINT32 ((const guint8 *) schm->data + 16);
9516
9517   GST_DEBUG_OBJECT (qtdemux,
9518       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9519       "protection_scheme_version: %#010x",
9520       GST_FOURCC_ARGS (stream->protection_scheme_type),
9521       stream->protection_scheme_version);
9522
9523   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9524   if (!schi) {
9525     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9526     return FALSE;
9527   }
9528   if (stream->protection_scheme_type == FOURCC_cenc) {
9529     QtDemuxCencSampleSetInfo *info;
9530     GNode *tenc;
9531     const guint8 *tenc_data;
9532     guint32 isEncrypted;
9533     guint8 iv_size;
9534     const guint8 *default_kid;
9535     GstBuffer *kid_buf;
9536
9537     if (G_UNLIKELY (!stream->protection_scheme_info))
9538       stream->protection_scheme_info =
9539           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9540
9541     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9542
9543     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9544     if (!tenc) {
9545       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9546           "which is mandatory for Common Encryption");
9547       return FALSE;
9548     }
9549     tenc_data = (const guint8 *) tenc->data + 12;
9550     isEncrypted = QT_UINT24 (tenc_data);
9551     iv_size = QT_UINT8 (tenc_data + 3);
9552     default_kid = (tenc_data + 4);
9553     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9554     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9555     if (info->default_properties)
9556       gst_structure_free (info->default_properties);
9557     info->default_properties =
9558         gst_structure_new ("application/x-cenc",
9559         "iv_size", G_TYPE_UINT, iv_size,
9560         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9561         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9562     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9563         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9564     gst_buffer_unref (kid_buf);
9565   }
9566   return TRUE;
9567 }
9568
9569 /* parse the traks.
9570  * With each track we associate a new QtDemuxStream that contains all the info
9571  * about the trak.
9572  * traks that do not decode to something (like strm traks) will not have a pad.
9573  */
9574 static gboolean
9575 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9576 {
9577   GstByteReader tkhd;
9578   int offset;
9579   GNode *mdia;
9580   GNode *mdhd;
9581   GNode *hdlr;
9582   GNode *minf;
9583   GNode *stbl;
9584   GNode *stsd;
9585   GNode *mp4a;
9586   GNode *mp4v;
9587   GNode *wave;
9588   GNode *esds;
9589   GNode *pasp;
9590   GNode *colr;
9591   GNode *tref;
9592   GNode *udta;
9593   GNode *svmi;
9594   GNode *fiel;
9595
9596   QtDemuxStream *stream = NULL;
9597   gboolean new_stream = FALSE;
9598   gchar *codec = NULL;
9599   const guint8 *stsd_data;
9600   const guint8 *stsd_entry_data;
9601   guint remaining_stsd_len;
9602   guint stsd_entry_count;
9603   guint stsd_index;
9604   guint16 lang_code;            /* quicktime lang code or packed iso code */
9605   guint32 version;
9606   guint32 tkhd_flags = 0;
9607   guint8 tkhd_version = 0;
9608   guint32 w = 0, h = 0;
9609   guint32 fourcc;
9610   guint value_size, stsd_len, len;
9611   guint32 track_id;
9612   guint32 dummy;
9613
9614   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9615
9616   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9617       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9618       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9619     goto corrupt_file;
9620
9621   /* pick between 64 or 32 bits */
9622   value_size = tkhd_version == 1 ? 8 : 4;
9623   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9624       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9625     goto corrupt_file;
9626
9627   if (!qtdemux->got_moov) {
9628     if (qtdemux_find_stream (qtdemux, track_id))
9629       goto existing_stream;
9630     stream = _create_stream ();
9631     stream->track_id = track_id;
9632     new_stream = TRUE;
9633   } else {
9634     stream = qtdemux_find_stream (qtdemux, track_id);
9635     if (!stream) {
9636       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9637       goto skip_track;
9638     }
9639
9640     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9641
9642     /* flush samples data from this track from previous moov */
9643     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9644     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9645   }
9646   /* need defaults for fragments */
9647   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9648
9649   if ((tkhd_flags & 1) == 0)
9650     stream->disabled = TRUE;
9651
9652   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9653       tkhd_version, tkhd_flags, stream->track_id);
9654
9655   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9656     goto corrupt_file;
9657
9658   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9659     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9660     if (qtdemux->major_brand != FOURCC_mjp2 ||
9661         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9662       goto corrupt_file;
9663   }
9664
9665   len = QT_UINT32 ((guint8 *) mdhd->data);
9666   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9667   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9668   if (version == 0x01000000) {
9669     if (len < 38)
9670       goto corrupt_file;
9671     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9672     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9673     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9674   } else {
9675     if (len < 30)
9676       goto corrupt_file;
9677     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9678     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9679     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9680   }
9681
9682   if (lang_code < 0x400) {
9683     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9684   } else if (lang_code == 0x7fff) {
9685     stream->lang_id[0] = 0;     /* unspecified */
9686   } else {
9687     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9688     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9689     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9690     stream->lang_id[3] = 0;
9691   }
9692
9693   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9694       stream->timescale);
9695   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9696       stream->duration);
9697   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9698       lang_code, stream->lang_id);
9699
9700   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9701     goto corrupt_file;
9702
9703   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9704     /* chapters track reference */
9705     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9706     if (chap) {
9707       gsize length = GST_READ_UINT32_BE (chap->data);
9708       if (qtdemux->chapters_track_id)
9709         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9710
9711       if (length >= 12) {
9712         qtdemux->chapters_track_id =
9713             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9714       }
9715     }
9716   }
9717
9718   /* fragmented files may have bogus duration in moov */
9719   if (!qtdemux->fragmented &&
9720       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9721     guint64 tdur1, tdur2;
9722
9723     /* don't overflow */
9724     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9725     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9726
9727     /* HACK:
9728      * some of those trailers, nowadays, have prologue images that are
9729      * themselves video tracks as well. I haven't really found a way to
9730      * identify those yet, except for just looking at their duration. */
9731     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9732       GST_WARNING_OBJECT (qtdemux,
9733           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9734           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9735           "found, assuming preview image or something; skipping track",
9736           stream->duration, stream->timescale, qtdemux->duration,
9737           qtdemux->timescale);
9738       if (new_stream)
9739         gst_qtdemux_stream_free (qtdemux, stream);
9740       return TRUE;
9741     }
9742   }
9743
9744   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9745     goto corrupt_file;
9746
9747   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9748       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9749
9750   len = QT_UINT32 ((guint8 *) hdlr->data);
9751   if (len >= 20)
9752     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9753   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9754       GST_FOURCC_ARGS (stream->subtype));
9755
9756   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9757     goto corrupt_file;
9758
9759   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9760     goto corrupt_file;
9761
9762   /*parse svmi header if existing */
9763   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9764   if (svmi) {
9765     len = QT_UINT32 ((guint8 *) svmi->data);
9766     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9767     if (!version) {
9768       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9769       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9770       guint8 frame_type, frame_layout;
9771
9772       /* MPEG-A stereo video */
9773       if (qtdemux->major_brand == FOURCC_ss02)
9774         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9775
9776       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9777       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9778       switch (frame_type) {
9779         case 0:
9780           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9781           break;
9782         case 1:
9783           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9784           break;
9785         case 2:
9786           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9787           break;
9788         case 3:
9789           /* mode 3 is primary/secondary view sequence, ie
9790            * left/right views in separate tracks. See section 7.2
9791            * of ISO/IEC 23000-11:2009 */
9792           GST_FIXME_OBJECT (qtdemux,
9793               "Implement stereo video in separate streams");
9794       }
9795
9796       if ((frame_layout & 0x1) == 0)
9797         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9798
9799       GST_LOG_OBJECT (qtdemux,
9800           "StereoVideo: composition type: %u, is_left_first: %u",
9801           frame_type, frame_layout);
9802       stream->multiview_mode = mode;
9803       stream->multiview_flags = flags;
9804     }
9805   }
9806
9807   /* parse rest of tkhd */
9808   if (stream->subtype == FOURCC_vide) {
9809     guint32 matrix[9];
9810
9811     /* version 1 uses some 64-bit ints */
9812     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9813       goto corrupt_file;
9814
9815     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9816       goto corrupt_file;
9817
9818     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9819         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9820       goto corrupt_file;
9821
9822     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9823         &stream->stream_tags);
9824   }
9825
9826   /* parse stsd */
9827   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9828     goto corrupt_file;
9829   stsd_data = (const guint8 *) stsd->data;
9830
9831   /* stsd should at least have one entry */
9832   stsd_len = QT_UINT32 (stsd_data);
9833   if (stsd_len < 24) {
9834     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9835     if (stream->subtype == FOURCC_vivo) {
9836       if (new_stream)
9837         gst_qtdemux_stream_free (qtdemux, stream);
9838       return TRUE;
9839     } else {
9840       goto corrupt_file;
9841     }
9842   }
9843
9844   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9845   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9846   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9847   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9848
9849   stsd_entry_data = stsd_data + 16;
9850   remaining_stsd_len = stsd_len - 16;
9851   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9852     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9853
9854     /* and that entry should fit within stsd */
9855     len = QT_UINT32 (stsd_entry_data);
9856     if (len > remaining_stsd_len)
9857       goto corrupt_file;
9858
9859     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9860     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9861         GST_FOURCC_ARGS (entry->fourcc));
9862     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9863
9864     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9865       goto error_encrypted;
9866
9867     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9868       /* FIXME this looks wrong, there might be multiple children
9869        * with the same type */
9870       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9871       stream->protected = TRUE;
9872       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9873         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9874     }
9875
9876     if (stream->subtype == FOURCC_vide) {
9877       gboolean gray;
9878       gint depth, palette_size, palette_count;
9879       guint32 *palette_data = NULL;
9880
9881       entry->sampled = TRUE;
9882
9883       stream->display_width = w >> 16;
9884       stream->display_height = h >> 16;
9885
9886       offset = 16;
9887       if (len < 86)             /* TODO verify */
9888         goto corrupt_file;
9889
9890       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9891       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9892       entry->fps_n = 0;         /* this is filled in later */
9893       entry->fps_d = 0;         /* this is filled in later */
9894       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9895       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9896
9897       /* if color_table_id is 0, ctab atom must follow; however some files
9898        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9899        * if color table is not present we'll correct the value */
9900       if (entry->color_table_id == 0 &&
9901           (len < 90
9902               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9903         entry->color_table_id = -1;
9904       }
9905
9906       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9907           entry->width, entry->height, entry->bits_per_sample,
9908           entry->color_table_id);
9909
9910       depth = entry->bits_per_sample;
9911
9912       /* more than 32 bits means grayscale */
9913       gray = (depth > 32);
9914       /* low 32 bits specify the depth  */
9915       depth &= 0x1F;
9916
9917       /* different number of palette entries is determined by depth. */
9918       palette_count = 0;
9919       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9920         palette_count = (1 << depth);
9921       palette_size = palette_count * 4;
9922
9923       if (entry->color_table_id) {
9924         switch (palette_count) {
9925           case 0:
9926             break;
9927           case 2:
9928             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9929             break;
9930           case 4:
9931             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9932             break;
9933           case 16:
9934             if (gray)
9935               palette_data =
9936                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9937             else
9938               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9939             break;
9940           case 256:
9941             if (gray)
9942               palette_data =
9943                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9944             else
9945               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9946             break;
9947           default:
9948             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9949                 (_("The video in this file might not play correctly.")),
9950                 ("unsupported palette depth %d", depth));
9951             break;
9952         }
9953       } else {
9954         gint i, j, start, end;
9955
9956         if (len < 94)
9957           goto corrupt_file;
9958
9959         /* read table */
9960         start = QT_UINT32 (stsd_entry_data + offset + 70);
9961         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9962         end = QT_UINT16 (stsd_entry_data + offset + 76);
9963
9964         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9965             start, end, palette_count);
9966
9967         if (end > 255)
9968           end = 255;
9969         if (start > end)
9970           start = end;
9971
9972         if (len < 94 + (end - start) * 8)
9973           goto corrupt_file;
9974
9975         /* palette is always the same size */
9976         palette_data = g_malloc0 (256 * 4);
9977         palette_size = 256 * 4;
9978
9979         for (j = 0, i = start; i <= end; j++, i++) {
9980           guint32 a, r, g, b;
9981
9982           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9983           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9984           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9985           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9986
9987           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9988               (g & 0xff00) | (b >> 8);
9989         }
9990       }
9991
9992       if (entry->caps)
9993         gst_caps_unref (entry->caps);
9994
9995       entry->caps =
9996           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
9997           &codec);
9998       if (G_UNLIKELY (!entry->caps)) {
9999         g_free (palette_data);
10000         goto unknown_stream;
10001       }
10002
10003       if (codec) {
10004         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10005             GST_TAG_VIDEO_CODEC, codec, NULL);
10006         g_free (codec);
10007         codec = NULL;
10008       }
10009
10010       if (palette_data) {
10011         GstStructure *s;
10012
10013         if (entry->rgb8_palette)
10014           gst_memory_unref (entry->rgb8_palette);
10015         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10016             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10017
10018         s = gst_caps_get_structure (entry->caps, 0);
10019
10020         /* non-raw video has a palette_data property. raw video has the palette as
10021          * an extra plane that we append to the output buffers before we push
10022          * them*/
10023         if (!gst_structure_has_name (s, "video/x-raw")) {
10024           GstBuffer *palette;
10025
10026           palette = gst_buffer_new ();
10027           gst_buffer_append_memory (palette, entry->rgb8_palette);
10028           entry->rgb8_palette = NULL;
10029
10030           gst_caps_set_simple (entry->caps, "palette_data",
10031               GST_TYPE_BUFFER, palette, NULL);
10032           gst_buffer_unref (palette);
10033         }
10034       } else if (palette_count != 0) {
10035         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10036             (NULL), ("Unsupported palette depth %d", depth));
10037       }
10038
10039       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10040           QT_UINT16 (stsd_entry_data + offset + 32));
10041
10042       esds = NULL;
10043       pasp = NULL;
10044       colr = NULL;
10045       fiel = NULL;
10046       /* pick 'the' stsd child */
10047       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10048       if (!stream->protected) {
10049         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10050           mp4v = NULL;
10051         }
10052       } else {
10053         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10054           mp4v = NULL;
10055         }
10056       }
10057
10058       if (mp4v) {
10059         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10060         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10061         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10062         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10063       }
10064
10065       if (pasp) {
10066         const guint8 *pasp_data = (const guint8 *) pasp->data;
10067         gint len = QT_UINT32 (pasp_data);
10068
10069         if (len == 16) {
10070           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10071           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10072         } else {
10073           CUR_STREAM (stream)->par_w = 0;
10074           CUR_STREAM (stream)->par_h = 0;
10075         }
10076       } else {
10077         CUR_STREAM (stream)->par_w = 0;
10078         CUR_STREAM (stream)->par_h = 0;
10079       }
10080
10081       if (fiel) {
10082         const guint8 *fiel_data = (const guint8 *) fiel->data;
10083         gint len = QT_UINT32 (fiel_data);
10084
10085         if (len == 10) {
10086           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10087           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10088         }
10089       }
10090
10091       if (colr) {
10092         const guint8 *colr_data = (const guint8 *) colr->data;
10093         gint len = QT_UINT32 (colr_data);
10094
10095         if (len == 19 || len == 18) {
10096           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10097
10098           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10099             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10100             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10101             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10102             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10103
10104             switch (primaries) {
10105               case 1:
10106                 CUR_STREAM (stream)->colorimetry.primaries =
10107                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10108                 break;
10109               case 5:
10110                 CUR_STREAM (stream)->colorimetry.primaries =
10111                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10112                 break;
10113               case 6:
10114                 CUR_STREAM (stream)->colorimetry.primaries =
10115                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10116                 break;
10117               case 9:
10118                 CUR_STREAM (stream)->colorimetry.primaries =
10119                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10120                 break;
10121               default:
10122                 break;
10123             }
10124
10125             switch (transfer_function) {
10126               case 1:
10127                 CUR_STREAM (stream)->colorimetry.transfer =
10128                     GST_VIDEO_TRANSFER_BT709;
10129                 break;
10130               case 7:
10131                 CUR_STREAM (stream)->colorimetry.transfer =
10132                     GST_VIDEO_TRANSFER_SMPTE240M;
10133                 break;
10134               default:
10135                 break;
10136             }
10137
10138             switch (matrix) {
10139               case 1:
10140                 CUR_STREAM (stream)->colorimetry.matrix =
10141                     GST_VIDEO_COLOR_MATRIX_BT709;
10142                 break;
10143               case 6:
10144                 CUR_STREAM (stream)->colorimetry.matrix =
10145                     GST_VIDEO_COLOR_MATRIX_BT601;
10146                 break;
10147               case 7:
10148                 CUR_STREAM (stream)->colorimetry.matrix =
10149                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10150                 break;
10151               case 9:
10152                 CUR_STREAM (stream)->colorimetry.matrix =
10153                     GST_VIDEO_COLOR_MATRIX_BT2020;
10154                 break;
10155               default:
10156                 break;
10157             }
10158
10159             CUR_STREAM (stream)->colorimetry.range =
10160                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10161                 GST_VIDEO_COLOR_RANGE_16_235;
10162           } else {
10163             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10164           }
10165         } else {
10166           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10167         }
10168       }
10169
10170       if (esds) {
10171         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10172             stream->stream_tags);
10173       } else {
10174         switch (fourcc) {
10175           case FOURCC_H264:
10176           case FOURCC_avc1:
10177           case FOURCC_avc3:
10178           {
10179             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10180             const guint8 *avc_data = stsd_entry_data + 0x56;
10181
10182             /* find avcC */
10183             while (len >= 0x8) {
10184               gint size;
10185
10186               if (QT_UINT32 (avc_data) <= len)
10187                 size = QT_UINT32 (avc_data) - 0x8;
10188               else
10189                 size = len - 0x8;
10190
10191               if (size < 1)
10192                 /* No real data, so break out */
10193                 break;
10194
10195               switch (QT_FOURCC (avc_data + 0x4)) {
10196                 case FOURCC_avcC:
10197                 {
10198                   /* parse, if found */
10199                   GstBuffer *buf;
10200
10201                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10202
10203                   /* First 4 bytes are the length of the atom, the next 4 bytes
10204                    * are the fourcc, the next 1 byte is the version, and the
10205                    * subsequent bytes are profile_tier_level structure like data. */
10206                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10207                       avc_data + 8 + 1, size - 1);
10208                   buf = gst_buffer_new_and_alloc (size);
10209                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10210                   gst_caps_set_simple (entry->caps,
10211                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10212                   gst_buffer_unref (buf);
10213
10214                   break;
10215                 }
10216                 case FOURCC_strf:
10217                 {
10218                   GstBuffer *buf;
10219
10220                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10221
10222                   /* First 4 bytes are the length of the atom, the next 4 bytes
10223                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10224                    * next 1 byte is the version, and the
10225                    * subsequent bytes are sequence parameter set like data. */
10226
10227                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10228                   if (size > 1) {
10229                     gst_codec_utils_h264_caps_set_level_and_profile
10230                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10231
10232                     buf = gst_buffer_new_and_alloc (size);
10233                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10234                     gst_caps_set_simple (entry->caps,
10235                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10236                     gst_buffer_unref (buf);
10237                   }
10238                   break;
10239                 }
10240                 case FOURCC_btrt:
10241                 {
10242                   guint avg_bitrate, max_bitrate;
10243
10244                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10245                   if (size < 12)
10246                     break;
10247
10248                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10249                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10250
10251                   if (!max_bitrate && !avg_bitrate)
10252                     break;
10253
10254                   /* Some muxers seem to swap the average and maximum bitrates
10255                    * (I'm looking at you, YouTube), so we swap for sanity. */
10256                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10257                     guint temp = avg_bitrate;
10258
10259                     avg_bitrate = max_bitrate;
10260                     max_bitrate = temp;
10261                   }
10262
10263                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10264                     gst_tag_list_add (stream->stream_tags,
10265                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10266                         max_bitrate, NULL);
10267                   }
10268                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10269                     gst_tag_list_add (stream->stream_tags,
10270                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10271                         NULL);
10272                   }
10273
10274                   break;
10275                 }
10276
10277                 default:
10278                   break;
10279               }
10280
10281               len -= size + 8;
10282               avc_data += size + 8;
10283             }
10284
10285             break;
10286           }
10287           case FOURCC_H265:
10288           case FOURCC_hvc1:
10289           case FOURCC_hev1:
10290           {
10291             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10292             const guint8 *hevc_data = stsd_entry_data + 0x56;
10293
10294             /* find hevc */
10295             while (len >= 0x8) {
10296               gint size;
10297
10298               if (QT_UINT32 (hevc_data) <= len)
10299                 size = QT_UINT32 (hevc_data) - 0x8;
10300               else
10301                 size = len - 0x8;
10302
10303               if (size < 1)
10304                 /* No real data, so break out */
10305                 break;
10306
10307               switch (QT_FOURCC (hevc_data + 0x4)) {
10308                 case FOURCC_hvcC:
10309                 {
10310                   /* parse, if found */
10311                   GstBuffer *buf;
10312
10313                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10314
10315                   /* First 4 bytes are the length of the atom, the next 4 bytes
10316                    * are the fourcc, the next 1 byte is the version, and the
10317                    * subsequent bytes are sequence parameter set like data. */
10318                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10319                       (entry->caps, hevc_data + 8 + 1, size - 1);
10320
10321                   buf = gst_buffer_new_and_alloc (size);
10322                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10323                   gst_caps_set_simple (entry->caps,
10324                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10325                   gst_buffer_unref (buf);
10326                   break;
10327                 }
10328                 default:
10329                   break;
10330               }
10331               len -= size + 8;
10332               hevc_data += size + 8;
10333             }
10334             break;
10335           }
10336           case FOURCC_mp4v:
10337           case FOURCC_MP4V:
10338           case FOURCC_fmp4:
10339           case FOURCC_FMP4:
10340           case FOURCC_xvid:
10341           case FOURCC_XVID:
10342           {
10343             GNode *glbl;
10344
10345             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10346                 GST_FOURCC_ARGS (fourcc));
10347
10348             /* codec data might be in glbl extension atom */
10349             glbl = mp4v ?
10350                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10351             if (glbl) {
10352               guint8 *data;
10353               GstBuffer *buf;
10354               gint len;
10355
10356               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10357               data = glbl->data;
10358               len = QT_UINT32 (data);
10359               if (len > 0x8) {
10360                 len -= 0x8;
10361                 buf = gst_buffer_new_and_alloc (len);
10362                 gst_buffer_fill (buf, 0, data + 8, len);
10363                 gst_caps_set_simple (entry->caps,
10364                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10365                 gst_buffer_unref (buf);
10366               }
10367             }
10368             break;
10369           }
10370           case FOURCC_mjp2:
10371           {
10372             /* see annex I of the jpeg2000 spec */
10373             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10374             const guint8 *data;
10375             const gchar *colorspace = NULL;
10376             gint ncomp = 0;
10377             guint32 ncomp_map = 0;
10378             gint32 *comp_map = NULL;
10379             guint32 nchan_def = 0;
10380             gint32 *chan_def = NULL;
10381
10382             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10383             /* some required atoms */
10384             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10385             if (!mjp2)
10386               break;
10387             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10388             if (!jp2h)
10389               break;
10390
10391             /* number of components; redundant with info in codestream, but useful
10392                to a muxer */
10393             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10394             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10395               break;
10396             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10397
10398             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10399             if (!colr)
10400               break;
10401             GST_DEBUG_OBJECT (qtdemux, "found colr");
10402             /* extract colour space info */
10403             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10404               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10405                 case 16:
10406                   colorspace = "sRGB";
10407                   break;
10408                 case 17:
10409                   colorspace = "GRAY";
10410                   break;
10411                 case 18:
10412                   colorspace = "sYUV";
10413                   break;
10414                 default:
10415                   colorspace = NULL;
10416                   break;
10417               }
10418             }
10419             if (!colorspace)
10420               /* colr is required, and only values 16, 17, and 18 are specified,
10421                  so error if we have no colorspace */
10422               break;
10423
10424             /* extract component mapping */
10425             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10426             if (cmap) {
10427               guint32 cmap_len = 0;
10428               int i;
10429               cmap_len = QT_UINT32 (cmap->data);
10430               if (cmap_len >= 8) {
10431                 /* normal box, subtract off header */
10432                 cmap_len -= 8;
10433                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10434                 if (cmap_len % 4 == 0) {
10435                   ncomp_map = (cmap_len / 4);
10436                   comp_map = g_new0 (gint32, ncomp_map);
10437                   for (i = 0; i < ncomp_map; i++) {
10438                     guint16 cmp;
10439                     guint8 mtyp, pcol;
10440                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10441                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10442                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10443                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10444                   }
10445                 }
10446               }
10447             }
10448             /* extract channel definitions */
10449             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10450             if (cdef) {
10451               guint32 cdef_len = 0;
10452               int i;
10453               cdef_len = QT_UINT32 (cdef->data);
10454               if (cdef_len >= 10) {
10455                 /* normal box, subtract off header and len */
10456                 cdef_len -= 10;
10457                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10458                 if (cdef_len % 6 == 0) {
10459                   nchan_def = (cdef_len / 6);
10460                   chan_def = g_new0 (gint32, nchan_def);
10461                   for (i = 0; i < nchan_def; i++)
10462                     chan_def[i] = -1;
10463                   for (i = 0; i < nchan_def; i++) {
10464                     guint16 cn, typ, asoc;
10465                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10466                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10467                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10468                     if (cn < nchan_def) {
10469                       switch (typ) {
10470                         case 0:
10471                           chan_def[cn] = asoc;
10472                           break;
10473                         case 1:
10474                           chan_def[cn] = 0;     /* alpha */
10475                           break;
10476                         default:
10477                           chan_def[cn] = -typ;
10478                       }
10479                     }
10480                   }
10481                 }
10482               }
10483             }
10484
10485             gst_caps_set_simple (entry->caps,
10486                 "num-components", G_TYPE_INT, ncomp, NULL);
10487             gst_caps_set_simple (entry->caps,
10488                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10489
10490             if (comp_map) {
10491               GValue arr = { 0, };
10492               GValue elt = { 0, };
10493               int i;
10494               g_value_init (&arr, GST_TYPE_ARRAY);
10495               g_value_init (&elt, G_TYPE_INT);
10496               for (i = 0; i < ncomp_map; i++) {
10497                 g_value_set_int (&elt, comp_map[i]);
10498                 gst_value_array_append_value (&arr, &elt);
10499               }
10500               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10501                   "component-map", &arr);
10502               g_value_unset (&elt);
10503               g_value_unset (&arr);
10504               g_free (comp_map);
10505             }
10506
10507             if (chan_def) {
10508               GValue arr = { 0, };
10509               GValue elt = { 0, };
10510               int i;
10511               g_value_init (&arr, GST_TYPE_ARRAY);
10512               g_value_init (&elt, G_TYPE_INT);
10513               for (i = 0; i < nchan_def; i++) {
10514                 g_value_set_int (&elt, chan_def[i]);
10515                 gst_value_array_append_value (&arr, &elt);
10516               }
10517               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10518                   "channel-definitions", &arr);
10519               g_value_unset (&elt);
10520               g_value_unset (&arr);
10521               g_free (chan_def);
10522             }
10523
10524             /* some optional atoms */
10525             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10526             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10527
10528             /* indicate possible fields in caps */
10529             if (field) {
10530               data = (guint8 *) field->data + 8;
10531               if (*data != 1)
10532                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10533                     (gint) * data, NULL);
10534             }
10535             /* add codec_data if provided */
10536             if (prefix) {
10537               GstBuffer *buf;
10538               gint len;
10539
10540               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10541               data = prefix->data;
10542               len = QT_UINT32 (data);
10543               if (len > 0x8) {
10544                 len -= 0x8;
10545                 buf = gst_buffer_new_and_alloc (len);
10546                 gst_buffer_fill (buf, 0, data + 8, len);
10547                 gst_caps_set_simple (entry->caps,
10548                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10549                 gst_buffer_unref (buf);
10550               }
10551             }
10552             break;
10553           }
10554           case FOURCC_SVQ3:
10555           case FOURCC_VP31:
10556           {
10557             GstBuffer *buf;
10558             GstBuffer *seqh = NULL;
10559             const guint8 *gamma_data = NULL;
10560             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10561
10562             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10563                 &seqh);
10564             if (gamma_data) {
10565               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10566                   QT_FP32 (gamma_data), NULL);
10567             }
10568             if (seqh) {
10569               /* sorry for the bad name, but we don't know what this is, other
10570                * than its own fourcc */
10571               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10572                   NULL);
10573               gst_buffer_unref (seqh);
10574             }
10575
10576             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10577             buf = gst_buffer_new_and_alloc (len);
10578             gst_buffer_fill (buf, 0, stsd_data, len);
10579             gst_caps_set_simple (entry->caps,
10580                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10581             gst_buffer_unref (buf);
10582             break;
10583           }
10584           case FOURCC_jpeg:
10585           {
10586             /* https://developer.apple.com/standards/qtff-2001.pdf,
10587              * page 92, "Video Sample Description", under table 3.1 */
10588             GstByteReader br;
10589
10590             const gint compressor_offset =
10591                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10592             const gint min_size = compressor_offset + 32 + 2 + 2;
10593             GNode *jpeg;
10594             guint32 len;
10595             guint16 color_table_id = 0;
10596             gboolean ok;
10597
10598             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10599
10600             /* recover information on interlaced/progressive */
10601             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10602             if (!jpeg)
10603               break;
10604
10605             len = QT_UINT32 (jpeg->data);
10606             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10607                 min_size);
10608             if (len >= min_size) {
10609               gst_byte_reader_init (&br, jpeg->data, len);
10610
10611               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10612               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10613               if (color_table_id != 0) {
10614                 /* the spec says there can be concatenated chunks in the data, and we want
10615                  * to find one called field. Walk through them. */
10616                 gint offset = min_size;
10617                 while (offset + 8 < len) {
10618                   guint32 size = 0, tag;
10619                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10620                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10621                   if (!ok || size < 8) {
10622                     GST_WARNING_OBJECT (qtdemux,
10623                         "Failed to walk optional chunk list");
10624                     break;
10625                   }
10626                   GST_DEBUG_OBJECT (qtdemux,
10627                       "Found optional %4.4s chunk, size %u",
10628                       (const char *) &tag, size);
10629                   if (tag == FOURCC_fiel) {
10630                     guint8 n_fields = 0, ordering = 0;
10631                     gst_byte_reader_get_uint8 (&br, &n_fields);
10632                     gst_byte_reader_get_uint8 (&br, &ordering);
10633                     if (n_fields == 1 || n_fields == 2) {
10634                       GST_DEBUG_OBJECT (qtdemux,
10635                           "Found fiel tag with %u fields, ordering %u",
10636                           n_fields, ordering);
10637                       if (n_fields == 2)
10638                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10639                             "interlace-mode", G_TYPE_STRING, "interleaved",
10640                             NULL);
10641                     } else {
10642                       GST_WARNING_OBJECT (qtdemux,
10643                           "Found fiel tag with invalid fields (%u)", n_fields);
10644                     }
10645                   }
10646                   offset += size;
10647                 }
10648               } else {
10649                 GST_DEBUG_OBJECT (qtdemux,
10650                     "Color table ID is 0, not trying to get interlacedness");
10651               }
10652             } else {
10653               GST_WARNING_OBJECT (qtdemux,
10654                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10655             }
10656
10657             break;
10658           }
10659           case FOURCC_rle_:
10660           case FOURCC_WRLE:
10661           {
10662             gst_caps_set_simple (entry->caps,
10663                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10664                 NULL);
10665             break;
10666           }
10667           case FOURCC_XiTh:
10668           {
10669             GNode *xith, *xdxt;
10670
10671             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10672             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10673             if (!xith)
10674               break;
10675
10676             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10677             if (!xdxt)
10678               break;
10679
10680             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10681             /* collect the headers and store them in a stream list so that we can
10682              * send them out first */
10683             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10684             break;
10685           }
10686           case FOURCC_ovc1:
10687           {
10688             GNode *ovc1;
10689             guint8 *ovc1_data;
10690             guint ovc1_len;
10691             GstBuffer *buf;
10692
10693             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10694             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10695             if (!ovc1)
10696               break;
10697             ovc1_data = ovc1->data;
10698             ovc1_len = QT_UINT32 (ovc1_data);
10699             if (ovc1_len <= 198) {
10700               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10701               break;
10702             }
10703             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10704             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10705             gst_caps_set_simple (entry->caps,
10706                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10707             gst_buffer_unref (buf);
10708             break;
10709           }
10710           case FOURCC_vc_1:
10711           {
10712             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10713             const guint8 *vc1_data = stsd_entry_data + 0x56;
10714
10715             /* find dvc1 */
10716             while (len >= 8) {
10717               gint size;
10718
10719               if (QT_UINT32 (vc1_data) <= len)
10720                 size = QT_UINT32 (vc1_data) - 8;
10721               else
10722                 size = len - 8;
10723
10724               if (size < 1)
10725                 /* No real data, so break out */
10726                 break;
10727
10728               switch (QT_FOURCC (vc1_data + 0x4)) {
10729                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10730                 {
10731                   GstBuffer *buf;
10732
10733                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10734                   buf = gst_buffer_new_and_alloc (size);
10735                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10736                   gst_caps_set_simple (entry->caps,
10737                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10738                   gst_buffer_unref (buf);
10739                   break;
10740                 }
10741                 default:
10742                   break;
10743               }
10744               len -= size + 8;
10745               vc1_data += size + 8;
10746             }
10747             break;
10748           }
10749           default:
10750             break;
10751         }
10752       }
10753
10754       GST_INFO_OBJECT (qtdemux,
10755           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10756           GST_FOURCC_ARGS (fourcc), entry->caps);
10757
10758     } else if (stream->subtype == FOURCC_soun) {
10759       int version, samplesize;
10760       guint16 compression_id;
10761       gboolean amrwb = FALSE;
10762
10763       offset = 16;
10764       /* sample description entry (16) + sound sample description v0 (20) */
10765       if (len < 36)
10766         goto corrupt_file;
10767
10768       version = QT_UINT32 (stsd_entry_data + offset);
10769       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10770       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10771       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10772       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10773
10774       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10775       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10776           QT_UINT32 (stsd_entry_data + offset + 4));
10777       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10778       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10779       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10780       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10781           QT_UINT16 (stsd_entry_data + offset + 14));
10782       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10783
10784       if (compression_id == 0xfffe)
10785         entry->sampled = TRUE;
10786
10787       /* first assume uncompressed audio */
10788       entry->bytes_per_sample = samplesize / 8;
10789       entry->samples_per_frame = entry->n_channels;
10790       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10791       entry->samples_per_packet = entry->samples_per_frame;
10792       entry->bytes_per_packet = entry->bytes_per_sample;
10793
10794       offset = 36;
10795       switch (fourcc) {
10796           /* Yes, these have to be hard-coded */
10797         case FOURCC_MAC6:
10798         {
10799           entry->samples_per_packet = 6;
10800           entry->bytes_per_packet = 1;
10801           entry->bytes_per_frame = 1 * entry->n_channels;
10802           entry->bytes_per_sample = 1;
10803           entry->samples_per_frame = 6 * entry->n_channels;
10804           break;
10805         }
10806         case FOURCC_MAC3:
10807         {
10808           entry->samples_per_packet = 3;
10809           entry->bytes_per_packet = 1;
10810           entry->bytes_per_frame = 1 * entry->n_channels;
10811           entry->bytes_per_sample = 1;
10812           entry->samples_per_frame = 3 * entry->n_channels;
10813           break;
10814         }
10815         case FOURCC_ima4:
10816         {
10817           entry->samples_per_packet = 64;
10818           entry->bytes_per_packet = 34;
10819           entry->bytes_per_frame = 34 * entry->n_channels;
10820           entry->bytes_per_sample = 2;
10821           entry->samples_per_frame = 64 * entry->n_channels;
10822           break;
10823         }
10824         case FOURCC_ulaw:
10825         case FOURCC_alaw:
10826         {
10827           entry->samples_per_packet = 1;
10828           entry->bytes_per_packet = 1;
10829           entry->bytes_per_frame = 1 * entry->n_channels;
10830           entry->bytes_per_sample = 1;
10831           entry->samples_per_frame = 1 * entry->n_channels;
10832           break;
10833         }
10834         case FOURCC_agsm:
10835         {
10836           entry->samples_per_packet = 160;
10837           entry->bytes_per_packet = 33;
10838           entry->bytes_per_frame = 33 * entry->n_channels;
10839           entry->bytes_per_sample = 2;
10840           entry->samples_per_frame = 160 * entry->n_channels;
10841           break;
10842         }
10843         default:
10844           break;
10845       }
10846
10847       if (version == 0x00010000) {
10848         /* sample description entry (16) + sound sample description v1 (20+16) */
10849         if (len < 52)
10850           goto corrupt_file;
10851
10852         switch (fourcc) {
10853           case FOURCC_twos:
10854           case FOURCC_sowt:
10855           case FOURCC_raw_:
10856           case FOURCC_lpcm:
10857             break;
10858           default:
10859           {
10860             /* only parse extra decoding config for non-pcm audio */
10861             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10862             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10863             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10864             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10865
10866             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10867                 entry->samples_per_packet);
10868             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10869                 entry->bytes_per_packet);
10870             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10871                 entry->bytes_per_frame);
10872             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10873                 entry->bytes_per_sample);
10874
10875             if (!entry->sampled && entry->bytes_per_packet) {
10876               entry->samples_per_frame = (entry->bytes_per_frame /
10877                   entry->bytes_per_packet) * entry->samples_per_packet;
10878               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10879                   entry->samples_per_frame);
10880             }
10881             break;
10882           }
10883         }
10884       } else if (version == 0x00020000) {
10885         union
10886         {
10887           gdouble fp;
10888           guint64 val;
10889         } qtfp;
10890
10891         /* sample description entry (16) + sound sample description v2 (56) */
10892         if (len < 72)
10893           goto corrupt_file;
10894
10895         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10896         entry->rate = qtfp.fp;
10897         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10898
10899         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10900         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10901         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10902         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10903             QT_UINT32 (stsd_entry_data + offset + 20));
10904         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10905             QT_UINT32 (stsd_entry_data + offset + 24));
10906         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10907             QT_UINT32 (stsd_entry_data + offset + 28));
10908         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10909             QT_UINT32 (stsd_entry_data + offset + 32));
10910       } else if (version != 0x00000) {
10911         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10912             version);
10913       }
10914
10915       if (entry->caps)
10916         gst_caps_unref (entry->caps);
10917
10918       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10919           stsd_entry_data + 32, len - 16, &codec);
10920
10921       switch (fourcc) {
10922         case FOURCC_in24:
10923         {
10924           GNode *enda;
10925           GNode *in24;
10926
10927           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10928
10929           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10930           if (!enda) {
10931             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10932             if (wave)
10933               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10934           }
10935           if (enda) {
10936             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10937             gst_caps_set_simple (entry->caps,
10938                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10939                 NULL);
10940           }
10941           break;
10942         }
10943         case FOURCC_owma:
10944         {
10945           const guint8 *owma_data;
10946           const gchar *codec_name = NULL;
10947           guint owma_len;
10948           GstBuffer *buf;
10949           gint version = 1;
10950           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10951           /* FIXME this should also be gst_riff_strf_auds,
10952            * but the latter one is actually missing bits-per-sample :( */
10953           typedef struct
10954           {
10955             gint16 wFormatTag;
10956             gint16 nChannels;
10957             gint32 nSamplesPerSec;
10958             gint32 nAvgBytesPerSec;
10959             gint16 nBlockAlign;
10960             gint16 wBitsPerSample;
10961             gint16 cbSize;
10962           } WAVEFORMATEX;
10963           WAVEFORMATEX *wfex;
10964
10965           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10966           owma_data = stsd_entry_data;
10967           owma_len = QT_UINT32 (owma_data);
10968           if (owma_len <= 54) {
10969             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10970             break;
10971           }
10972           wfex = (WAVEFORMATEX *) (owma_data + 36);
10973           buf = gst_buffer_new_and_alloc (owma_len - 54);
10974           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10975           if (wfex->wFormatTag == 0x0161) {
10976             codec_name = "Windows Media Audio";
10977             version = 2;
10978           } else if (wfex->wFormatTag == 0x0162) {
10979             codec_name = "Windows Media Audio 9 Pro";
10980             version = 3;
10981           } else if (wfex->wFormatTag == 0x0163) {
10982             codec_name = "Windows Media Audio 9 Lossless";
10983             /* is that correct? gstffmpegcodecmap.c is missing it, but
10984              * fluendo codec seems to support it */
10985             version = 4;
10986           }
10987
10988           gst_caps_set_simple (entry->caps,
10989               "codec_data", GST_TYPE_BUFFER, buf,
10990               "wmaversion", G_TYPE_INT, version,
10991               "block_align", G_TYPE_INT,
10992               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
10993               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
10994               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
10995               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
10996           gst_buffer_unref (buf);
10997
10998           if (codec_name) {
10999             g_free (codec);
11000             codec = g_strdup (codec_name);
11001           }
11002           break;
11003         }
11004         case FOURCC_wma_:
11005         {
11006           gint len = QT_UINT32 (stsd_entry_data) - offset;
11007           const guint8 *wfex_data = stsd_entry_data + offset;
11008           const gchar *codec_name = NULL;
11009           gint version = 1;
11010           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11011           /* FIXME this should also be gst_riff_strf_auds,
11012            * but the latter one is actually missing bits-per-sample :( */
11013           typedef struct
11014           {
11015             gint16 wFormatTag;
11016             gint16 nChannels;
11017             gint32 nSamplesPerSec;
11018             gint32 nAvgBytesPerSec;
11019             gint16 nBlockAlign;
11020             gint16 wBitsPerSample;
11021             gint16 cbSize;
11022           } WAVEFORMATEX;
11023           WAVEFORMATEX wfex;
11024
11025           /* FIXME: unify with similar wavformatex parsing code above */
11026           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11027
11028           /* find wfex */
11029           while (len >= 8) {
11030             gint size;
11031
11032             if (QT_UINT32 (wfex_data) <= len)
11033               size = QT_UINT32 (wfex_data) - 8;
11034             else
11035               size = len - 8;
11036
11037             if (size < 1)
11038               /* No real data, so break out */
11039               break;
11040
11041             switch (QT_FOURCC (wfex_data + 4)) {
11042               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11043               {
11044                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11045
11046                 if (size < 8 + 18)
11047                   break;
11048
11049                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11050                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11051                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11052                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11053                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11054                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11055                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11056
11057                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11058                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11059                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11060                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11061                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11062                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11063
11064                 if (wfex.wFormatTag == 0x0161) {
11065                   codec_name = "Windows Media Audio";
11066                   version = 2;
11067                 } else if (wfex.wFormatTag == 0x0162) {
11068                   codec_name = "Windows Media Audio 9 Pro";
11069                   version = 3;
11070                 } else if (wfex.wFormatTag == 0x0163) {
11071                   codec_name = "Windows Media Audio 9 Lossless";
11072                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11073                    * fluendo codec seems to support it */
11074                   version = 4;
11075                 }
11076
11077                 gst_caps_set_simple (entry->caps,
11078                     "wmaversion", G_TYPE_INT, version,
11079                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11080                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11081                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11082                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11083
11084                 if (size > wfex.cbSize) {
11085                   GstBuffer *buf;
11086
11087                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11088                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11089                       size - wfex.cbSize);
11090                   gst_caps_set_simple (entry->caps,
11091                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11092                   gst_buffer_unref (buf);
11093                 } else {
11094                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11095                 }
11096
11097                 if (codec_name) {
11098                   g_free (codec);
11099                   codec = g_strdup (codec_name);
11100                 }
11101                 break;
11102               }
11103               default:
11104                 break;
11105             }
11106             len -= size + 8;
11107             wfex_data += size + 8;
11108           }
11109           break;
11110         }
11111         case FOURCC_opus:
11112         {
11113           const guint8 *opus_data;
11114           guint8 *channel_mapping = NULL;
11115           guint32 rate;
11116           guint8 channels;
11117           guint8 channel_mapping_family;
11118           guint8 stream_count;
11119           guint8 coupled_count;
11120           guint8 i;
11121
11122           opus_data = stsd_entry_data;
11123
11124           channels = GST_READ_UINT8 (opus_data + 45);
11125           rate = GST_READ_UINT32_LE (opus_data + 48);
11126           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11127           stream_count = GST_READ_UINT8 (opus_data + 55);
11128           coupled_count = GST_READ_UINT8 (opus_data + 56);
11129
11130           if (channels > 0) {
11131             channel_mapping = g_malloc (channels * sizeof (guint8));
11132             for (i = 0; i < channels; i++)
11133               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11134           }
11135
11136           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11137               channel_mapping_family, stream_count, coupled_count,
11138               channel_mapping);
11139           break;
11140         }
11141         default:
11142           break;
11143       }
11144
11145       if (codec) {
11146         GstStructure *s;
11147         gint bitrate = 0;
11148
11149         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11150             GST_TAG_AUDIO_CODEC, codec, NULL);
11151         g_free (codec);
11152         codec = NULL;
11153
11154         /* some bitrate info may have ended up in caps */
11155         s = gst_caps_get_structure (entry->caps, 0);
11156         gst_structure_get_int (s, "bitrate", &bitrate);
11157         if (bitrate > 0)
11158           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11159               GST_TAG_BITRATE, bitrate, NULL);
11160       }
11161
11162       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11163       if (!stream->protected) {
11164       } else {
11165         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11166           mp4v = NULL;
11167         }
11168       }
11169       if (stream->protected && fourcc == FOURCC_mp4a) {
11170         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11171           mp4a = NULL;
11172         }
11173       } else {
11174         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11175           mp4a = NULL;
11176         }
11177       }
11178
11179       wave = NULL;
11180       esds = NULL;
11181       if (mp4a) {
11182         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11183         if (wave)
11184           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11185         if (!esds)
11186           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11187       }
11188
11189
11190       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11191          16 bits is a byte-swapped wave-style codec identifier,
11192          and we can find a WAVE header internally to a 'wave' atom here.
11193          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11194          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11195          is big-endian).
11196        */
11197       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11198         if (len < offset + 20) {
11199           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11200         } else {
11201           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11202           const guint8 *data = stsd_entry_data + offset + 16;
11203           GNode *wavenode;
11204           GNode *waveheadernode;
11205
11206           wavenode = g_node_new ((guint8 *) data);
11207           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11208             const guint8 *waveheader;
11209             guint32 headerlen;
11210
11211             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11212             if (waveheadernode) {
11213               waveheader = (const guint8 *) waveheadernode->data;
11214               headerlen = QT_UINT32 (waveheader);
11215
11216               if (headerlen > 8) {
11217                 gst_riff_strf_auds *header = NULL;
11218                 GstBuffer *headerbuf;
11219                 GstBuffer *extra;
11220
11221                 waveheader += 8;
11222                 headerlen -= 8;
11223
11224                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11225                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11226
11227                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11228                         headerbuf, &header, &extra)) {
11229                   gst_caps_unref (entry->caps);
11230                   /* FIXME: Need to do something with the channel reorder map */
11231                   entry->caps =
11232                       gst_riff_create_audio_caps (header->format, NULL, header,
11233                       extra, NULL, NULL, NULL);
11234
11235                   if (extra)
11236                     gst_buffer_unref (extra);
11237                   g_free (header);
11238                 }
11239               }
11240             } else
11241               GST_DEBUG ("Didn't find waveheadernode for this codec");
11242           }
11243           g_node_destroy (wavenode);
11244         }
11245       } else if (esds) {
11246         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11247             stream->stream_tags);
11248       } else {
11249         switch (fourcc) {
11250 #if 0
11251             /* FIXME: what is in the chunk? */
11252           case FOURCC_QDMC:
11253           {
11254             gint len = QT_UINT32 (stsd_data);
11255
11256             /* seems to be always = 116 = 0x74 */
11257             break;
11258           }
11259 #endif
11260           case FOURCC_QDM2:
11261           {
11262             gint len = QT_UINT32 (stsd_entry_data);
11263
11264             if (len > 0x3C) {
11265               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11266
11267               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11268               gst_caps_set_simple (entry->caps,
11269                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11270               gst_buffer_unref (buf);
11271             }
11272             gst_caps_set_simple (entry->caps,
11273                 "samplesize", G_TYPE_INT, samplesize, NULL);
11274             break;
11275           }
11276           case FOURCC_alac:
11277           {
11278             GNode *alac, *wave = NULL;
11279
11280             /* apparently, m4a has this atom appended directly in the stsd entry,
11281              * while mov has it in a wave atom */
11282             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11283             if (alac) {
11284               /* alac now refers to stsd entry atom */
11285               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11286               if (wave)
11287                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11288               else
11289                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11290             }
11291             if (alac) {
11292               const guint8 *alac_data = alac->data;
11293               gint len = QT_UINT32 (alac->data);
11294               GstBuffer *buf;
11295
11296               if (len < 36) {
11297                 GST_DEBUG_OBJECT (qtdemux,
11298                     "discarding alac atom with unexpected len %d", len);
11299               } else {
11300                 /* codec-data contains alac atom size and prefix,
11301                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11302                 buf = gst_buffer_new_and_alloc (len);
11303                 gst_buffer_fill (buf, 0, alac->data, len);
11304                 gst_caps_set_simple (entry->caps,
11305                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11306                 gst_buffer_unref (buf);
11307
11308                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11309                 entry->n_channels = QT_UINT8 (alac_data + 21);
11310                 entry->rate = QT_UINT32 (alac_data + 32);
11311               }
11312             }
11313             gst_caps_set_simple (entry->caps,
11314                 "samplesize", G_TYPE_INT, samplesize, NULL);
11315             break;
11316           }
11317           case FOURCC_fLaC:
11318           {
11319             /* The codingname of the sample entry is 'fLaC' */
11320             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11321
11322             if (flac) {
11323               /* The 'dfLa' box is added to the sample entry to convey
11324                  initializing information for the decoder. */
11325               const GNode *dfla =
11326                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11327
11328               if (dfla) {
11329                 const guint32 len = QT_UINT32 (dfla->data);
11330
11331                 /* Must contain at least dfLa box header (12),
11332                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11333                 if (len < 50) {
11334                   GST_DEBUG_OBJECT (qtdemux,
11335                       "discarding dfla atom with unexpected len %d", len);
11336                 } else {
11337                   /* skip dfLa header to get the METADATA_BLOCKs */
11338                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11339                   const guint32 metadata_blocks_len = len - 12;
11340
11341                   gchar *stream_marker = g_strdup ("fLaC");
11342                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11343                       strlen (stream_marker));
11344
11345                   guint32 index = 0;
11346                   guint32 remainder = 0;
11347                   guint32 block_size = 0;
11348                   gboolean is_last = FALSE;
11349
11350                   GValue array = G_VALUE_INIT;
11351                   GValue value = G_VALUE_INIT;
11352
11353                   g_value_init (&array, GST_TYPE_ARRAY);
11354                   g_value_init (&value, GST_TYPE_BUFFER);
11355
11356                   gst_value_set_buffer (&value, block);
11357                   gst_value_array_append_value (&array, &value);
11358                   g_value_reset (&value);
11359
11360                   gst_buffer_unref (block);
11361
11362                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11363                    * of data, and we haven't already finished parsing */
11364                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11365                     remainder = metadata_blocks_len - index;
11366
11367                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11368                     block_size = 4 +
11369                         (metadata_blocks[index + 1] << 16) +
11370                         (metadata_blocks[index + 2] << 8) +
11371                         metadata_blocks[index + 3];
11372
11373                     /* be careful not to read off end of box */
11374                     if (block_size > remainder) {
11375                       break;
11376                     }
11377
11378                     is_last = metadata_blocks[index] >> 7;
11379
11380                     block = gst_buffer_new_and_alloc (block_size);
11381
11382                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11383                         block_size);
11384
11385                     gst_value_set_buffer (&value, block);
11386                     gst_value_array_append_value (&array, &value);
11387                     g_value_reset (&value);
11388
11389                     gst_buffer_unref (block);
11390
11391                     index += block_size;
11392                   }
11393
11394                   /* only append the metadata if we successfully read all of it */
11395                   if (is_last) {
11396                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11397                             (stream)->caps, 0), "streamheader", &array);
11398                   } else {
11399                     GST_WARNING_OBJECT (qtdemux,
11400                         "discarding all METADATA_BLOCKs due to invalid "
11401                         "block_size %d at idx %d, rem %d", block_size, index,
11402                         remainder);
11403                   }
11404
11405                   g_value_unset (&value);
11406                   g_value_unset (&array);
11407
11408                   /* The sample rate obtained from the stsd may not be accurate
11409                    * since it cannot represent rates greater than 65535Hz, so
11410                    * override that value with the sample rate from the
11411                    * METADATA_BLOCK_STREAMINFO block */
11412                   CUR_STREAM (stream)->rate =
11413                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11414                 }
11415               }
11416             }
11417             break;
11418           }
11419           case FOURCC_sawb:
11420             /* Fallthrough! */
11421             amrwb = TRUE;
11422           case FOURCC_samr:
11423           {
11424             gint len = QT_UINT32 (stsd_entry_data);
11425
11426             if (len > 0x24) {
11427               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11428               guint bitrate;
11429
11430               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11431
11432               /* If we have enough data, let's try to get the 'damr' atom. See
11433                * the 3GPP container spec (26.244) for more details. */
11434               if ((len - 0x34) > 8 &&
11435                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11436                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11437                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11438               }
11439
11440               gst_caps_set_simple (entry->caps,
11441                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11442               gst_buffer_unref (buf);
11443             }
11444             break;
11445           }
11446           case FOURCC_mp4a:
11447           {
11448             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11449             gint len = QT_UINT32 (stsd_entry_data);
11450
11451             if (len >= 34) {
11452               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11453
11454               if (sound_version == 1) {
11455                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11456                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11457                 guint8 codec_data[2];
11458                 GstBuffer *buf;
11459                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11460
11461                 gint sample_rate_index =
11462                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11463
11464                 /* build AAC codec data */
11465                 codec_data[0] = profile << 3;
11466                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11467                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11468                 codec_data[1] |= (channels & 0xF) << 3;
11469
11470                 buf = gst_buffer_new_and_alloc (2);
11471                 gst_buffer_fill (buf, 0, codec_data, 2);
11472                 gst_caps_set_simple (entry->caps,
11473                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11474                 gst_buffer_unref (buf);
11475               }
11476             }
11477             break;
11478           }
11479           case FOURCC_lpcm:
11480             /* Fully handled elsewhere */
11481             break;
11482           default:
11483             GST_INFO_OBJECT (qtdemux,
11484                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11485             break;
11486         }
11487       }
11488       GST_INFO_OBJECT (qtdemux,
11489           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11490           GST_FOURCC_ARGS (fourcc), entry->caps);
11491
11492     } else if (stream->subtype == FOURCC_strm) {
11493       if (fourcc == FOURCC_rtsp) {
11494         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11495       } else {
11496         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11497             GST_FOURCC_ARGS (fourcc));
11498         goto unknown_stream;
11499       }
11500       entry->sampled = TRUE;
11501     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11502         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11503
11504       entry->sampled = TRUE;
11505       entry->sparse = TRUE;
11506
11507       entry->caps =
11508           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11509           &codec);
11510       if (codec) {
11511         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11512             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11513         g_free (codec);
11514         codec = NULL;
11515       }
11516
11517       /* hunt for sort-of codec data */
11518       switch (fourcc) {
11519         case FOURCC_mp4s:
11520         {
11521           GNode *mp4s = NULL;
11522           GNode *esds = NULL;
11523
11524           /* look for palette in a stsd->mp4s->esds sub-atom */
11525           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11526           if (mp4s)
11527             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11528           if (esds == NULL) {
11529             /* Invalid STSD */
11530             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11531             break;
11532           }
11533
11534           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11535               stream->stream_tags);
11536           break;
11537         }
11538         default:
11539           GST_INFO_OBJECT (qtdemux,
11540               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11541           break;
11542       }
11543       GST_INFO_OBJECT (qtdemux,
11544           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11545           GST_FOURCC_ARGS (fourcc), entry->caps);
11546     } else {
11547       /* everything in 1 sample */
11548       entry->sampled = TRUE;
11549
11550       entry->caps =
11551           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11552           &codec);
11553
11554       if (entry->caps == NULL)
11555         goto unknown_stream;
11556
11557       if (codec) {
11558         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11559             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11560         g_free (codec);
11561         codec = NULL;
11562       }
11563     }
11564
11565     /* promote to sampled format */
11566     if (entry->fourcc == FOURCC_samr) {
11567       /* force mono 8000 Hz for AMR */
11568       entry->sampled = TRUE;
11569       entry->n_channels = 1;
11570       entry->rate = 8000;
11571     } else if (entry->fourcc == FOURCC_sawb) {
11572       /* force mono 16000 Hz for AMR-WB */
11573       entry->sampled = TRUE;
11574       entry->n_channels = 1;
11575       entry->rate = 16000;
11576     } else if (entry->fourcc == FOURCC_mp4a) {
11577       entry->sampled = TRUE;
11578     }
11579
11580
11581     stsd_entry_data += len;
11582     remaining_stsd_len -= len;
11583
11584   }
11585
11586   /* collect sample information */
11587   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11588     goto samples_failed;
11589
11590   if (qtdemux->fragmented) {
11591     guint64 offset;
11592
11593     /* need all moov samples as basis; probably not many if any at all */
11594     /* prevent moof parsing taking of at this time */
11595     offset = qtdemux->moof_offset;
11596     qtdemux->moof_offset = 0;
11597     if (stream->n_samples &&
11598         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11599       qtdemux->moof_offset = offset;
11600       goto samples_failed;
11601     }
11602     qtdemux->moof_offset = 0;
11603     /* movie duration more reliable in this case (e.g. mehd) */
11604     if (qtdemux->segment.duration &&
11605         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11606       stream->duration =
11607           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11608   }
11609
11610   /* configure segments */
11611   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11612     goto segments_failed;
11613
11614   /* add some language tag, if useful */
11615   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11616       strcmp (stream->lang_id, "und")) {
11617     const gchar *lang_code;
11618
11619     /* convert ISO 639-2 code to ISO 639-1 */
11620     lang_code = gst_tag_get_language_code (stream->lang_id);
11621     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11622         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11623   }
11624
11625   /* Check for UDTA tags */
11626   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11627     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11628   }
11629
11630   /* now we are ready to add the stream */
11631   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11632     goto too_many_streams;
11633
11634   if (!qtdemux->got_moov) {
11635     qtdemux->streams[qtdemux->n_streams] = stream;
11636     qtdemux->n_streams++;
11637     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11638   }
11639
11640   return TRUE;
11641
11642 /* ERRORS */
11643 skip_track:
11644   {
11645     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11646     if (new_stream)
11647       gst_qtdemux_stream_free (qtdemux, stream);
11648     return TRUE;
11649   }
11650 corrupt_file:
11651   {
11652     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11653         (_("This file is corrupt and cannot be played.")), (NULL));
11654     if (new_stream)
11655       gst_qtdemux_stream_free (qtdemux, stream);
11656     return FALSE;
11657   }
11658 error_encrypted:
11659   {
11660     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11661     if (new_stream)
11662       gst_qtdemux_stream_free (qtdemux, stream);
11663     return FALSE;
11664   }
11665 samples_failed:
11666 segments_failed:
11667   {
11668     /* we posted an error already */
11669     /* free stbl sub-atoms */
11670     gst_qtdemux_stbl_free (stream);
11671     if (new_stream)
11672       gst_qtdemux_stream_free (qtdemux, stream);
11673     return FALSE;
11674   }
11675 existing_stream:
11676   {
11677     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11678         track_id);
11679     if (new_stream)
11680       gst_qtdemux_stream_free (qtdemux, stream);
11681     return TRUE;
11682   }
11683 unknown_stream:
11684   {
11685     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11686         GST_FOURCC_ARGS (stream->subtype));
11687     if (new_stream)
11688       gst_qtdemux_stream_free (qtdemux, stream);
11689     return TRUE;
11690   }
11691 too_many_streams:
11692   {
11693     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11694         (_("This file contains too many streams. Only playing first %d"),
11695             GST_QTDEMUX_MAX_STREAMS), (NULL));
11696     return TRUE;
11697   }
11698 }
11699
11700 /* If we can estimate the overall bitrate, and don't have information about the
11701  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11702  * the overall bitrate minus the sum of the bitrates of all other streams. This
11703  * should be useful for the common case where we have one audio and one video
11704  * stream and can estimate the bitrate of one, but not the other. */
11705 static void
11706 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11707 {
11708   QtDemuxStream *stream = NULL;
11709   gint64 size, sys_bitrate, sum_bitrate = 0;
11710   GstClockTime duration;
11711   gint i;
11712   guint bitrate;
11713
11714   if (qtdemux->fragmented)
11715     return;
11716
11717   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11718
11719   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11720       || size <= 0) {
11721     GST_DEBUG_OBJECT (qtdemux,
11722         "Size in bytes of the stream not known - bailing");
11723     return;
11724   }
11725
11726   /* Subtract the header size */
11727   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11728       size, qtdemux->header_size);
11729
11730   if (size < qtdemux->header_size)
11731     return;
11732
11733   size = size - qtdemux->header_size;
11734
11735   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11736     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11737     return;
11738   }
11739
11740   for (i = 0; i < qtdemux->n_streams; i++) {
11741     switch (qtdemux->streams[i]->subtype) {
11742       case FOURCC_soun:
11743       case FOURCC_vide:
11744         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11745             CUR_STREAM (qtdemux->streams[i])->caps);
11746         /* retrieve bitrate, prefer avg then max */
11747         bitrate = 0;
11748         if (qtdemux->streams[i]->stream_tags) {
11749           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11750               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11751           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11752           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11753               GST_TAG_NOMINAL_BITRATE, &bitrate);
11754           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11755           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11756               GST_TAG_BITRATE, &bitrate);
11757           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11758         }
11759         if (bitrate)
11760           sum_bitrate += bitrate;
11761         else {
11762           if (stream) {
11763             GST_DEBUG_OBJECT (qtdemux,
11764                 ">1 stream with unknown bitrate - bailing");
11765             return;
11766           } else
11767             stream = qtdemux->streams[i];
11768         }
11769
11770       default:
11771         /* For other subtypes, we assume no significant impact on bitrate */
11772         break;
11773     }
11774   }
11775
11776   if (!stream) {
11777     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11778     return;
11779   }
11780
11781   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11782
11783   if (sys_bitrate < sum_bitrate) {
11784     /* This can happen, since sum_bitrate might be derived from maximum
11785      * bitrates and not average bitrates */
11786     GST_DEBUG_OBJECT (qtdemux,
11787         "System bitrate less than sum bitrate - bailing");
11788     return;
11789   }
11790
11791   bitrate = sys_bitrate - sum_bitrate;
11792   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11793       ", Stream bitrate = %u", sys_bitrate, bitrate);
11794
11795   if (!stream->stream_tags)
11796     stream->stream_tags = gst_tag_list_new_empty ();
11797   else
11798     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11799
11800   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11801       GST_TAG_BITRATE, bitrate, NULL);
11802 }
11803
11804 static GstFlowReturn
11805 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11806 {
11807   gint i;
11808   GstFlowReturn ret = GST_FLOW_OK;
11809
11810   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11811
11812   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11813     QtDemuxStream *stream = qtdemux->streams[i];
11814     guint32 sample_num = 0;
11815
11816     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11817         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11818
11819     if (qtdemux->fragmented) {
11820       /* need all moov samples first */
11821       GST_OBJECT_LOCK (qtdemux);
11822       while (stream->n_samples == 0)
11823         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11824           break;
11825       GST_OBJECT_UNLOCK (qtdemux);
11826     } else {
11827       /* discard any stray moof */
11828       qtdemux->moof_offset = 0;
11829     }
11830
11831     /* prepare braking */
11832     if (ret != GST_FLOW_ERROR)
11833       ret = GST_FLOW_OK;
11834
11835     /* in pull mode, we should have parsed some sample info by now;
11836      * and quite some code will not handle no samples.
11837      * in push mode, we'll just have to deal with it */
11838     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11839       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11840       gst_qtdemux_remove_stream (qtdemux, i);
11841       i--;
11842       continue;
11843     }
11844
11845     /* parse the initial sample for use in setting the frame rate cap */
11846     while (sample_num == 0 && sample_num < stream->n_samples) {
11847       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11848         break;
11849       ++sample_num;
11850     }
11851     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11852       stream->first_duration = stream->samples[0].duration;
11853       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11854           stream->track_id, stream->first_duration);
11855     }
11856   }
11857
11858   return ret;
11859 }
11860
11861 static GstFlowReturn
11862 qtdemux_expose_streams (GstQTDemux * qtdemux)
11863 {
11864   gint i;
11865   GSList *oldpads = NULL;
11866   GSList *iter;
11867
11868   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11869
11870   for (i = 0; i < qtdemux->n_streams; i++) {
11871     QtDemuxStream *stream = qtdemux->streams[i];
11872     GstPad *oldpad = stream->pad;
11873     GstTagList *list;
11874
11875     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11876         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11877
11878     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11879         stream->track_id == qtdemux->chapters_track_id) {
11880       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11881          so that it doesn't look like a subtitle track */
11882       gst_qtdemux_remove_stream (qtdemux, i);
11883       i--;
11884       continue;
11885     }
11886
11887     /* now we have all info and can expose */
11888     list = stream->stream_tags;
11889     stream->stream_tags = NULL;
11890     if (oldpad)
11891       oldpads = g_slist_prepend (oldpads, oldpad);
11892     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11893       return GST_FLOW_ERROR;
11894   }
11895
11896   gst_qtdemux_guess_bitrate (qtdemux);
11897
11898   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11899
11900   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11901     GstPad *oldpad = iter->data;
11902     GstEvent *event;
11903
11904     event = gst_event_new_eos ();
11905     if (qtdemux->segment_seqnum)
11906       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11907
11908     gst_pad_push_event (oldpad, event);
11909     gst_pad_set_active (oldpad, FALSE);
11910     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11911     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11912     gst_object_unref (oldpad);
11913   }
11914
11915   /* check if we should post a redirect in case there is a single trak
11916    * and it is a redirecting trak */
11917   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11918     GstMessage *m;
11919
11920     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11921         "an external content");
11922     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11923         gst_structure_new ("redirect",
11924             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11925             NULL));
11926     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11927     qtdemux->posted_redirect = TRUE;
11928   }
11929
11930   for (i = 0; i < qtdemux->n_streams; i++) {
11931     QtDemuxStream *stream = qtdemux->streams[i];
11932
11933     qtdemux_do_allocation (qtdemux, stream);
11934   }
11935
11936   qtdemux->exposed = TRUE;
11937   return GST_FLOW_OK;
11938 }
11939
11940 /* check if major or compatible brand is 3GP */
11941 static inline gboolean
11942 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11943 {
11944   if (major) {
11945     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11946         FOURCC_3g__);
11947   } else if (qtdemux->comp_brands != NULL) {
11948     GstMapInfo map;
11949     guint8 *data;
11950     gsize size;
11951     gboolean res = FALSE;
11952
11953     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11954     data = map.data;
11955     size = map.size;
11956     while (size >= 4) {
11957       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11958           FOURCC_3g__);
11959       data += 4;
11960       size -= 4;
11961     }
11962     gst_buffer_unmap (qtdemux->comp_brands, &map);
11963     return res;
11964   } else {
11965     return FALSE;
11966   }
11967 }
11968
11969 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11970 static inline gboolean
11971 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11972 {
11973   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11974       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11975       || fourcc == FOURCC_albm;
11976 }
11977
11978 static void
11979 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11980     const char *tag, const char *dummy, GNode * node)
11981 {
11982   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11983   int offset;
11984   char *name;
11985   gchar *data;
11986   gdouble longitude, latitude, altitude;
11987   gint len;
11988
11989   len = QT_UINT32 (node->data);
11990   if (len <= 14)
11991     goto short_read;
11992
11993   data = node->data;
11994   offset = 14;
11995
11996   /* TODO: language code skipped */
11997
11998   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11999
12000   if (!name) {
12001     /* do not alarm in trivial case, but bail out otherwise */
12002     if (*(data + offset) != 0) {
12003       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12004           "giving up", tag);
12005     }
12006   } else {
12007     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12008         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12009     offset += strlen (name);
12010     g_free (name);
12011   }
12012
12013   if (len < offset + 2 + 4 + 4 + 4)
12014     goto short_read;
12015
12016   /* +1 +1 = skip null-terminator and location role byte */
12017   offset += 1 + 1;
12018   /* table in spec says unsigned, semantics say negative has meaning ... */
12019   longitude = QT_SFP32 (data + offset);
12020
12021   offset += 4;
12022   latitude = QT_SFP32 (data + offset);
12023
12024   offset += 4;
12025   altitude = QT_SFP32 (data + offset);
12026
12027   /* one invalid means all are invalid */
12028   if (longitude >= -180.0 && longitude <= 180.0 &&
12029       latitude >= -90.0 && latitude <= 90.0) {
12030     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12031         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12032         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12033         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12034   }
12035
12036   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12037
12038   return;
12039
12040   /* ERRORS */
12041 short_read:
12042   {
12043     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12044     return;
12045   }
12046 }
12047
12048
12049 static void
12050 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12051     const char *tag, const char *dummy, GNode * node)
12052 {
12053   guint16 y;
12054   GDate *date;
12055   gint len;
12056
12057   len = QT_UINT32 (node->data);
12058   if (len < 14)
12059     return;
12060
12061   y = QT_UINT16 ((guint8 *) node->data + 12);
12062   if (y == 0) {
12063     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12064     return;
12065   }
12066   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12067
12068   date = g_date_new_dmy (1, 1, y);
12069   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12070   g_date_free (date);
12071 }
12072
12073 static void
12074 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12075     const char *tag, const char *dummy, GNode * node)
12076 {
12077   int offset;
12078   char *tag_str = NULL;
12079   guint8 *entity;
12080   guint16 table;
12081   gint len;
12082
12083   len = QT_UINT32 (node->data);
12084   if (len <= 20)
12085     goto short_read;
12086
12087   offset = 12;
12088   entity = (guint8 *) node->data + offset;
12089   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12090     GST_DEBUG_OBJECT (qtdemux,
12091         "classification info: %c%c%c%c invalid classification entity",
12092         entity[0], entity[1], entity[2], entity[3]);
12093     return;
12094   }
12095
12096   offset += 4;
12097   table = QT_UINT16 ((guint8 *) node->data + offset);
12098
12099   /* Language code skipped */
12100
12101   offset += 4;
12102
12103   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12104    * XXXX: classification entity, fixed length 4 chars.
12105    * Y[YYYY]: classification table, max 5 chars.
12106    */
12107   tag_str = g_strdup_printf ("----://%u/%s",
12108       table, (char *) node->data + offset);
12109
12110   /* memcpy To be sure we're preserving byte order */
12111   memcpy (tag_str, entity, 4);
12112   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12113
12114   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12115
12116   g_free (tag_str);
12117
12118   return;
12119
12120   /* ERRORS */
12121 short_read:
12122   {
12123     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12124     return;
12125   }
12126 }
12127
12128 static gboolean
12129 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12130     const char *tag, const char *dummy, GNode * node)
12131 {
12132   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12133   GNode *data;
12134   char *s;
12135   int len;
12136   guint32 type;
12137   int offset;
12138   gboolean ret = TRUE;
12139   const gchar *charset = NULL;
12140
12141   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12142   if (data) {
12143     len = QT_UINT32 (data->data);
12144     type = QT_UINT32 ((guint8 *) data->data + 8);
12145     if (type == 0x00000001 && len > 16) {
12146       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12147           env_vars);
12148       if (s) {
12149         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12150         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12151         g_free (s);
12152       } else {
12153         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12154       }
12155     }
12156   } else {
12157     len = QT_UINT32 (node->data);
12158     type = QT_UINT32 ((guint8 *) node->data + 4);
12159     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12160       gint str_len;
12161       gint lang_code;
12162
12163       /* Type starts with the (C) symbol, so the next data is a list
12164        * of (string size(16), language code(16), string) */
12165
12166       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12167       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12168
12169       /* the string + fourcc + size + 2 16bit fields,
12170        * means that there are more tags in this atom */
12171       if (len > str_len + 8 + 4) {
12172         /* TODO how to represent the same tag in different languages? */
12173         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12174             "text alternatives, reading only first one");
12175       }
12176
12177       offset = 12;
12178       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12179       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12180
12181       if (lang_code < 0x800) {  /* MAC encoded string */
12182         charset = "mac";
12183       }
12184     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12185             QT_FOURCC ((guint8 *) node->data + 4))) {
12186       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12187
12188       /* we go for 3GP style encoding if major brands claims so,
12189        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12190       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12191           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12192               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12193         offset = 14;
12194         /* 16-bit Language code is ignored here as well */
12195         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12196       } else {
12197         goto normal;
12198       }
12199     } else {
12200     normal:
12201       offset = 8;
12202       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12203       ret = FALSE;              /* may have to fallback */
12204     }
12205     if (charset) {
12206       GError *err = NULL;
12207
12208       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12209           charset, NULL, NULL, &err);
12210       if (err) {
12211         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12212             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12213             err->message);
12214         g_error_free (err);
12215       }
12216     } else {
12217       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12218           len - offset, env_vars);
12219     }
12220     if (s) {
12221       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12222       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12223       g_free (s);
12224       ret = TRUE;
12225     } else {
12226       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12227     }
12228   }
12229   return ret;
12230 }
12231
12232 static void
12233 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12234     const char *tag, const char *dummy, GNode * node)
12235 {
12236   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12237 }
12238
12239 static void
12240 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12241     const char *tag, const char *dummy, GNode * node)
12242 {
12243   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12244   guint8 *data;
12245   char *s, *t, *k = NULL;
12246   int len;
12247   int offset;
12248   int count;
12249
12250   /* first try normal string tag if major brand not 3GP */
12251   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12252     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12253       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12254        * let's try it 3gpp way after minor safety check */
12255       data = node->data;
12256       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12257         return;
12258     } else
12259       return;
12260   }
12261
12262   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12263
12264   data = node->data;
12265
12266   len = QT_UINT32 (data);
12267   if (len < 15)
12268     goto short_read;
12269
12270   count = QT_UINT8 (data + 14);
12271   offset = 15;
12272   for (; count; count--) {
12273     gint slen;
12274
12275     if (offset + 1 > len)
12276       goto short_read;
12277     slen = QT_UINT8 (data + offset);
12278     offset += 1;
12279     if (offset + slen > len)
12280       goto short_read;
12281     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12282         slen, env_vars);
12283     if (s) {
12284       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12285       if (k) {
12286         t = g_strjoin (",", k, s, NULL);
12287         g_free (s);
12288         g_free (k);
12289         k = t;
12290       } else {
12291         k = s;
12292       }
12293     } else {
12294       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12295     }
12296     offset += slen;
12297   }
12298
12299 done:
12300   if (k) {
12301     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12302     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12303   }
12304   g_free (k);
12305
12306   return;
12307
12308   /* ERRORS */
12309 short_read:
12310   {
12311     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12312     goto done;
12313   }
12314 }
12315
12316 static void
12317 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12318     const char *tag1, const char *tag2, GNode * node)
12319 {
12320   GNode *data;
12321   int len;
12322   int type;
12323   int n1, n2;
12324
12325   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12326   if (data) {
12327     len = QT_UINT32 (data->data);
12328     type = QT_UINT32 ((guint8 *) data->data + 8);
12329     if (type == 0x00000000 && len >= 22) {
12330       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12331       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12332       if (n1 > 0) {
12333         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12334         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12335       }
12336       if (n2 > 0) {
12337         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12338         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12339       }
12340     }
12341   }
12342 }
12343
12344 static void
12345 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12346     const char *tag1, const char *dummy, GNode * node)
12347 {
12348   GNode *data;
12349   int len;
12350   int type;
12351   int n1;
12352
12353   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12354   if (data) {
12355     len = QT_UINT32 (data->data);
12356     type = QT_UINT32 ((guint8 *) data->data + 8);
12357     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12358     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12359     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12360       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12361       if (n1) {
12362         /* do not add bpm=0 */
12363         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12364         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12365             NULL);
12366       }
12367     }
12368   }
12369 }
12370
12371 static void
12372 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12373     const char *tag1, const char *dummy, GNode * node)
12374 {
12375   GNode *data;
12376   int len;
12377   int type;
12378   guint32 num;
12379
12380   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12381   if (data) {
12382     len = QT_UINT32 (data->data);
12383     type = QT_UINT32 ((guint8 *) data->data + 8);
12384     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12385     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12386     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12387       num = QT_UINT32 ((guint8 *) data->data + 16);
12388       if (num) {
12389         /* do not add num=0 */
12390         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12391         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12392       }
12393     }
12394   }
12395 }
12396
12397 static void
12398 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12399     const char *tag1, const char *dummy, GNode * node)
12400 {
12401   GNode *data;
12402   int len;
12403   int type;
12404   GstSample *sample;
12405
12406   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12407   if (data) {
12408     len = QT_UINT32 (data->data);
12409     type = QT_UINT32 ((guint8 *) data->data + 8);
12410     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12411     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12412       GstTagImageType image_type;
12413
12414       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12415         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12416       else
12417         image_type = GST_TAG_IMAGE_TYPE_NONE;
12418
12419       if ((sample =
12420               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12421                   len - 16, image_type))) {
12422         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12423         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12424         gst_sample_unref (sample);
12425       }
12426     }
12427   }
12428 }
12429
12430 static void
12431 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12432     const char *tag, const char *dummy, GNode * node)
12433 {
12434   GNode *data;
12435   char *s;
12436   int len;
12437   int type;
12438
12439   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12440   if (data) {
12441     len = QT_UINT32 (data->data);
12442     type = QT_UINT32 ((guint8 *) data->data + 8);
12443     if (type == 0x00000001 && len > 16) {
12444       guint y, m = 1, d = 1;
12445       gint ret;
12446
12447       s = g_strndup ((char *) data->data + 16, len - 16);
12448       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12449       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12450       if (ret >= 1 && y > 1500 && y < 3000) {
12451         GDate *date;
12452
12453         date = g_date_new_dmy (d, m, y);
12454         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12455         g_date_free (date);
12456       } else {
12457         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12458       }
12459       g_free (s);
12460     }
12461   }
12462 }
12463
12464 static void
12465 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12466     const char *tag, const char *dummy, GNode * node)
12467 {
12468   GNode *data;
12469
12470   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12471
12472   /* re-route to normal string tag if major brand says so
12473    * or no data atom and compatible brand suggests so */
12474   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12475       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12476     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12477     return;
12478   }
12479
12480   if (data) {
12481     guint len, type, n;
12482
12483     len = QT_UINT32 (data->data);
12484     type = QT_UINT32 ((guint8 *) data->data + 8);
12485     if (type == 0x00000000 && len >= 18) {
12486       n = QT_UINT16 ((guint8 *) data->data + 16);
12487       if (n > 0) {
12488         const gchar *genre;
12489
12490         genre = gst_tag_id3_genre_get (n - 1);
12491         if (genre != NULL) {
12492           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12493           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12494         }
12495       }
12496     }
12497   }
12498 }
12499
12500 static void
12501 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12502     const gchar * tag, guint8 * data, guint32 datasize)
12503 {
12504   gdouble value;
12505   gchar *datacopy;
12506
12507   /* make a copy to have \0 at the end */
12508   datacopy = g_strndup ((gchar *) data, datasize);
12509
12510   /* convert the str to double */
12511   if (sscanf (datacopy, "%lf", &value) == 1) {
12512     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12513     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12514   } else {
12515     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12516         datacopy);
12517   }
12518   g_free (datacopy);
12519 }
12520
12521
12522 static void
12523 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12524     const char *tag, const char *tag_bis, GNode * node)
12525 {
12526   GNode *mean;
12527   GNode *name;
12528   GNode *data;
12529   guint32 meansize;
12530   guint32 namesize;
12531   guint32 datatype;
12532   guint32 datasize;
12533   const gchar *meanstr;
12534   const gchar *namestr;
12535
12536   /* checking the whole ---- atom size for consistency */
12537   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12538     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12539     return;
12540   }
12541
12542   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12543   if (!mean) {
12544     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12545     return;
12546   }
12547
12548   meansize = QT_UINT32 (mean->data);
12549   if (meansize <= 12) {
12550     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12551     return;
12552   }
12553   meanstr = ((gchar *) mean->data) + 12;
12554   meansize -= 12;
12555
12556   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12557   if (!name) {
12558     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12559     return;
12560   }
12561
12562   namesize = QT_UINT32 (name->data);
12563   if (namesize <= 12) {
12564     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12565     return;
12566   }
12567   namestr = ((gchar *) name->data) + 12;
12568   namesize -= 12;
12569
12570   /*
12571    * Data atom is:
12572    * uint32 - size
12573    * uint32 - name
12574    * uint8  - version
12575    * uint24 - data type
12576    * uint32 - all 0
12577    * rest   - the data
12578    */
12579   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12580   if (!data) {
12581     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12582     return;
12583   }
12584   datasize = QT_UINT32 (data->data);
12585   if (datasize <= 16) {
12586     GST_WARNING_OBJECT (demux, "Data atom too small");
12587     return;
12588   }
12589   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12590
12591   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12592       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12593     static const struct
12594     {
12595       const gchar name[28];
12596       const gchar tag[28];
12597     } tags[] = {
12598       {
12599       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12600       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12601       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12602       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12603       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12604       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12605       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12606       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12607     };
12608     int i;
12609
12610     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12611       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12612         switch (gst_tag_get_type (tags[i].tag)) {
12613           case G_TYPE_DOUBLE:
12614             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12615                 ((guint8 *) data->data) + 16, datasize - 16);
12616             break;
12617           case G_TYPE_STRING:
12618             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12619             break;
12620           default:
12621             /* not reached */
12622             break;
12623         }
12624         break;
12625       }
12626     }
12627     if (i == G_N_ELEMENTS (tags))
12628       goto unknown_tag;
12629   } else {
12630     goto unknown_tag;
12631   }
12632
12633   return;
12634
12635 /* errors */
12636 unknown_tag:
12637 #ifndef GST_DISABLE_GST_DEBUG
12638   {
12639     gchar *namestr_dbg;
12640     gchar *meanstr_dbg;
12641
12642     meanstr_dbg = g_strndup (meanstr, meansize);
12643     namestr_dbg = g_strndup (namestr, namesize);
12644
12645     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12646         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12647
12648     g_free (namestr_dbg);
12649     g_free (meanstr_dbg);
12650   }
12651 #endif
12652   return;
12653 }
12654
12655 static void
12656 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12657     const char *tag_bis, GNode * node)
12658 {
12659   guint8 *data;
12660   GstBuffer *buf;
12661   guint len;
12662   GstTagList *id32_taglist = NULL;
12663
12664   GST_LOG_OBJECT (demux, "parsing ID32");
12665
12666   data = node->data;
12667   len = GST_READ_UINT32_BE (data);
12668
12669   /* need at least full box and language tag */
12670   if (len < 12 + 2)
12671     return;
12672
12673   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12674   gst_buffer_fill (buf, 0, data + 14, len - 14);
12675
12676   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12677   if (id32_taglist) {
12678     GST_LOG_OBJECT (demux, "parsing ok");
12679     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12680     gst_tag_list_unref (id32_taglist);
12681   } else {
12682     GST_LOG_OBJECT (demux, "parsing failed");
12683   }
12684
12685   gst_buffer_unref (buf);
12686 }
12687
12688 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12689     const char *tag, const char *tag_bis, GNode * node);
12690
12691 /* unmapped tags
12692 FOURCC_pcst -> if media is a podcast -> bool
12693 FOURCC_cpil -> if media is part of a compilation -> bool
12694 FOURCC_pgap -> if media is part of a gapless context -> bool
12695 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12696 */
12697
12698 static const struct
12699 {
12700   guint32 fourcc;
12701   const gchar *gst_tag;
12702   const gchar *gst_tag_bis;
12703   const GstQTDemuxAddTagFunc func;
12704 } add_funcs[] = {
12705   {
12706   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12707   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12708   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12709   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12710   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12711   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12712   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12713   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12714   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12715   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12716   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12717   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12718   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12719   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12720   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12721   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12722   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12723   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12724   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12725   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12726   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12727   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12728   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12729         qtdemux_tag_add_num}, {
12730   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12731         qtdemux_tag_add_num}, {
12732   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12733   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12734   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12735   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12736   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12737   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12738   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12739   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12740   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12741   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12742   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12743   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12744   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12745   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12746   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12747   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12748   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12749   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12750         qtdemux_tag_add_classification}, {
12751   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12752   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12753   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12754
12755     /* This is a special case, some tags are stored in this
12756      * 'reverse dns naming', according to:
12757      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12758      * bug #614471
12759      */
12760   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12761     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12762   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12763 };
12764
12765 struct _GstQtDemuxTagList
12766 {
12767   GstQTDemux *demux;
12768   GstTagList *taglist;
12769 };
12770 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12771
12772 static void
12773 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12774 {
12775   gint len;
12776   guint8 *data;
12777   GstBuffer *buf;
12778   gchar *media_type;
12779   const gchar *style;
12780   GstSample *sample;
12781   GstStructure *s;
12782   guint i;
12783   guint8 ndata[4];
12784   GstQTDemux *demux = qtdemuxtaglist->demux;
12785   GstTagList *taglist = qtdemuxtaglist->taglist;
12786
12787   data = node->data;
12788   len = QT_UINT32 (data);
12789   buf = gst_buffer_new_and_alloc (len);
12790   gst_buffer_fill (buf, 0, data, len);
12791
12792   /* heuristic to determine style of tag */
12793   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12794       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12795     style = "itunes";
12796   else if (demux->major_brand == FOURCC_qt__)
12797     style = "quicktime";
12798   /* fall back to assuming iso/3gp tag style */
12799   else
12800     style = "iso";
12801
12802   /* santize the name for the caps. */
12803   for (i = 0; i < 4; i++) {
12804     guint8 d = data[4 + i];
12805     if (g_ascii_isalnum (d))
12806       ndata[i] = g_ascii_tolower (d);
12807     else
12808       ndata[i] = '_';
12809   }
12810
12811   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12812       ndata[0], ndata[1], ndata[2], ndata[3]);
12813   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12814
12815   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12816   sample = gst_sample_new (buf, NULL, NULL, s);
12817   gst_buffer_unref (buf);
12818   g_free (media_type);
12819
12820   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12821       len, s);
12822
12823   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12824       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12825
12826   gst_sample_unref (sample);
12827 }
12828
12829 static void
12830 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12831 {
12832   GNode *meta;
12833   GNode *ilst;
12834   GNode *xmp_;
12835   GNode *node;
12836   gint i;
12837   GstQtDemuxTagList demuxtaglist;
12838
12839   demuxtaglist.demux = qtdemux;
12840   demuxtaglist.taglist = taglist;
12841
12842   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12843   if (meta != NULL) {
12844     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12845     if (ilst == NULL) {
12846       GST_LOG_OBJECT (qtdemux, "no ilst");
12847       return;
12848     }
12849   } else {
12850     ilst = udta;
12851     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12852   }
12853
12854   i = 0;
12855   while (i < G_N_ELEMENTS (add_funcs)) {
12856     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12857     if (node) {
12858       gint len;
12859
12860       len = QT_UINT32 (node->data);
12861       if (len < 12) {
12862         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12863             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12864       } else {
12865         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12866             add_funcs[i].gst_tag_bis, node);
12867       }
12868       g_node_destroy (node);
12869     } else {
12870       i++;
12871     }
12872   }
12873
12874   /* parsed nodes have been removed, pass along remainder as blob */
12875   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12876       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12877
12878   /* parse up XMP_ node if existing */
12879   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12880   if (xmp_ != NULL) {
12881     GstBuffer *buf;
12882     GstTagList *xmptaglist;
12883
12884     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12885         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12886     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12887     gst_buffer_unref (buf);
12888
12889     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12890   } else {
12891     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12892   }
12893 }
12894
12895 typedef struct
12896 {
12897   GstStructure *structure;      /* helper for sort function */
12898   gchar *location;
12899   guint min_req_bitrate;
12900   guint min_req_qt_version;
12901 } GstQtReference;
12902
12903 static gint
12904 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12905 {
12906   GstQtReference *ref_a = (GstQtReference *) a;
12907   GstQtReference *ref_b = (GstQtReference *) b;
12908
12909   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12910     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12911
12912   /* known bitrates go before unknown; higher bitrates go first */
12913   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12914 }
12915
12916 /* sort the redirects and post a message for the application.
12917  */
12918 static void
12919 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12920 {
12921   GstQtReference *best;
12922   GstStructure *s;
12923   GstMessage *msg;
12924   GValue list_val = { 0, };
12925   GList *l;
12926
12927   g_assert (references != NULL);
12928
12929   references = g_list_sort (references, qtdemux_redirects_sort_func);
12930
12931   best = (GstQtReference *) references->data;
12932
12933   g_value_init (&list_val, GST_TYPE_LIST);
12934
12935   for (l = references; l != NULL; l = l->next) {
12936     GstQtReference *ref = (GstQtReference *) l->data;
12937     GValue struct_val = { 0, };
12938
12939     ref->structure = gst_structure_new ("redirect",
12940         "new-location", G_TYPE_STRING, ref->location, NULL);
12941
12942     if (ref->min_req_bitrate > 0) {
12943       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12944           ref->min_req_bitrate, NULL);
12945     }
12946
12947     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12948     g_value_set_boxed (&struct_val, ref->structure);
12949     gst_value_list_append_value (&list_val, &struct_val);
12950     g_value_unset (&struct_val);
12951     /* don't free anything here yet, since we need best->structure below */
12952   }
12953
12954   g_assert (best != NULL);
12955   s = gst_structure_copy (best->structure);
12956
12957   if (g_list_length (references) > 1) {
12958     gst_structure_set_value (s, "locations", &list_val);
12959   }
12960
12961   g_value_unset (&list_val);
12962
12963   for (l = references; l != NULL; l = l->next) {
12964     GstQtReference *ref = (GstQtReference *) l->data;
12965
12966     gst_structure_free (ref->structure);
12967     g_free (ref->location);
12968     g_free (ref);
12969   }
12970   g_list_free (references);
12971
12972   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12973   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12974   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12975   qtdemux->posted_redirect = TRUE;
12976 }
12977
12978 /* look for redirect nodes, collect all redirect information and
12979  * process it.
12980  */
12981 static gboolean
12982 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12983 {
12984   GNode *rmra, *rmda, *rdrf;
12985
12986   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12987   if (rmra) {
12988     GList *redirects = NULL;
12989
12990     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12991     while (rmda) {
12992       GstQtReference ref = { NULL, NULL, 0, 0 };
12993       GNode *rmdr, *rmvc;
12994
12995       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12996         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12997         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12998             ref.min_req_bitrate);
12999       }
13000
13001       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13002         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13003         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13004
13005 #ifndef GST_DISABLE_GST_DEBUG
13006         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13007 #endif
13008         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13009
13010         GST_LOG_OBJECT (qtdemux,
13011             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13012             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13013             bitmask, check_type);
13014         if (package == FOURCC_qtim && check_type == 0) {
13015           ref.min_req_qt_version = version;
13016         }
13017       }
13018
13019       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13020       if (rdrf) {
13021         guint32 ref_type;
13022         guint8 *ref_data;
13023         guint ref_len;
13024
13025         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13026         if (ref_len > 20) {
13027           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13028           ref_data = (guint8 *) rdrf->data + 20;
13029           if (ref_type == FOURCC_alis) {
13030             guint record_len, record_version, fn_len;
13031
13032             if (ref_len > 70) {
13033               /* MacOSX alias record, google for alias-layout.txt */
13034               record_len = QT_UINT16 (ref_data + 4);
13035               record_version = QT_UINT16 (ref_data + 4 + 2);
13036               fn_len = QT_UINT8 (ref_data + 50);
13037               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13038                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13039               }
13040             } else {
13041               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13042                   ref_len);
13043             }
13044           } else if (ref_type == FOURCC_url_) {
13045             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13046           } else {
13047             GST_DEBUG_OBJECT (qtdemux,
13048                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13049                 GST_FOURCC_ARGS (ref_type));
13050           }
13051           if (ref.location != NULL) {
13052             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13053             redirects =
13054                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13055           } else {
13056             GST_WARNING_OBJECT (qtdemux,
13057                 "Failed to extract redirect location from rdrf atom");
13058           }
13059         } else {
13060           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13061         }
13062       }
13063
13064       /* look for others */
13065       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13066     }
13067
13068     if (redirects != NULL) {
13069       qtdemux_process_redirects (qtdemux, redirects);
13070     }
13071   }
13072   return TRUE;
13073 }
13074
13075 static GstTagList *
13076 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13077 {
13078   const gchar *fmt;
13079
13080   if (tags == NULL) {
13081     tags = gst_tag_list_new_empty ();
13082     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13083   }
13084
13085   if (qtdemux->major_brand == FOURCC_mjp2)
13086     fmt = "Motion JPEG 2000";
13087   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13088     fmt = "3GP";
13089   else if (qtdemux->major_brand == FOURCC_qt__)
13090     fmt = "Quicktime";
13091   else if (qtdemux->fragmented)
13092     fmt = "ISO fMP4";
13093   else
13094     fmt = "ISO MP4/M4A";
13095
13096   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13097       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13098
13099   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13100       fmt, NULL);
13101
13102   return tags;
13103 }
13104
13105 /* we have read the complete moov node now.
13106  * This function parses all of the relevant info, creates the traks and
13107  * prepares all data structures for playback
13108  */
13109 static gboolean
13110 qtdemux_parse_tree (GstQTDemux * qtdemux)
13111 {
13112   GNode *mvhd;
13113   GNode *trak;
13114   GNode *udta;
13115   GNode *mvex;
13116   GstClockTime duration;
13117   GNode *pssh;
13118   guint64 creation_time;
13119   GstDateTime *datetime = NULL;
13120   gint version;
13121
13122   /* make sure we have a usable taglist */
13123   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13124
13125   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13126   if (mvhd == NULL) {
13127     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13128     return qtdemux_parse_redirects (qtdemux);
13129   }
13130
13131   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13132   if (version == 1) {
13133     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13134     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13135     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13136   } else if (version == 0) {
13137     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13138     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13139     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13140   } else {
13141     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13142     return FALSE;
13143   }
13144
13145   /* Moving qt creation time (secs since 1904) to unix time */
13146   if (creation_time != 0) {
13147     /* Try to use epoch first as it should be faster and more commonly found */
13148     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13149       GTimeVal now;
13150
13151       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13152       /* some data cleansing sanity */
13153       g_get_current_time (&now);
13154       if (now.tv_sec + 24 * 3600 < creation_time) {
13155         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13156       } else {
13157         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13158       }
13159     } else {
13160       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13161       GDateTime *dt, *dt_local;
13162
13163       dt = g_date_time_add_seconds (base_dt, creation_time);
13164       dt_local = g_date_time_to_local (dt);
13165       datetime = gst_date_time_new_from_g_date_time (dt_local);
13166
13167       g_date_time_unref (base_dt);
13168       g_date_time_unref (dt);
13169     }
13170   }
13171   if (datetime) {
13172     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13173     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13174         datetime, NULL);
13175     gst_date_time_unref (datetime);
13176   }
13177
13178   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13179   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13180
13181   /* check for fragmented file and get some (default) data */
13182   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13183   if (mvex) {
13184     GNode *mehd;
13185     GstByteReader mehd_data;
13186
13187     /* let track parsing or anyone know weird stuff might happen ... */
13188     qtdemux->fragmented = TRUE;
13189
13190     /* compensate for total duration */
13191     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13192     if (mehd)
13193       qtdemux_parse_mehd (qtdemux, &mehd_data);
13194   }
13195
13196   /* set duration in the segment info */
13197   gst_qtdemux_get_duration (qtdemux, &duration);
13198   if (duration) {
13199     qtdemux->segment.duration = duration;
13200     /* also do not exceed duration; stop is set that way post seek anyway,
13201      * and segment activation falls back to duration,
13202      * whereas loop only checks stop, so let's align this here as well */
13203     qtdemux->segment.stop = duration;
13204   }
13205
13206   /* parse all traks */
13207   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13208   while (trak) {
13209     qtdemux_parse_trak (qtdemux, trak);
13210     /* iterate all siblings */
13211     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13212   }
13213
13214   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13215
13216   /* find tags */
13217   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13218   if (udta) {
13219     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13220   } else {
13221     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13222   }
13223
13224   /* maybe also some tags in meta box */
13225   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13226   if (udta) {
13227     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13228     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13229   } else {
13230     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13231   }
13232
13233   /* parse any protection system info */
13234   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13235   while (pssh) {
13236     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13237     qtdemux_parse_pssh (qtdemux, pssh);
13238     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13239   }
13240
13241   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13242
13243   return TRUE;
13244 }
13245
13246 /* taken from ffmpeg */
13247 static int
13248 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13249 {
13250   int count = 4;
13251   int len = 0;
13252
13253   while (count--) {
13254     int c;
13255
13256     if (ptr >= end)
13257       return -1;
13258
13259     c = *ptr++;
13260     len = (len << 7) | (c & 0x7f);
13261     if (!(c & 0x80))
13262       break;
13263   }
13264   *end_out = ptr;
13265   return len;
13266 }
13267
13268 /* this can change the codec originally present in @list */
13269 static void
13270 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13271     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13272 {
13273   int len = QT_UINT32 (esds->data);
13274   guint8 *ptr = esds->data;
13275   guint8 *end = ptr + len;
13276   int tag;
13277   guint8 *data_ptr = NULL;
13278   int data_len = 0;
13279   guint8 object_type_id = 0;
13280   const char *codec_name = NULL;
13281   GstCaps *caps = NULL;
13282
13283   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13284   ptr += 8;
13285   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13286   ptr += 4;
13287   while (ptr + 1 < end) {
13288     tag = QT_UINT8 (ptr);
13289     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13290     ptr++;
13291     len = read_descr_size (ptr, end, &ptr);
13292     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13293
13294     /* Check the stated amount of data is available for reading */
13295     if (len < 0 || ptr + len > end)
13296       break;
13297
13298     switch (tag) {
13299       case ES_DESCRIPTOR_TAG:
13300         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13301         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13302         ptr += 3;
13303         break;
13304       case DECODER_CONFIG_DESC_TAG:{
13305         guint max_bitrate, avg_bitrate;
13306
13307         object_type_id = QT_UINT8 (ptr);
13308         max_bitrate = QT_UINT32 (ptr + 5);
13309         avg_bitrate = QT_UINT32 (ptr + 9);
13310         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13311         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13312         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13313         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13314         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13315         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13316           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13317               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13318         }
13319         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13320           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13321               avg_bitrate, NULL);
13322         }
13323         ptr += 13;
13324         break;
13325       }
13326       case DECODER_SPECIFIC_INFO_TAG:
13327         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13328         if (object_type_id == 0xe0 && len == 0x40) {
13329           guint8 *data;
13330           GstStructure *s;
13331           guint32 clut[16];
13332           gint i;
13333
13334           GST_DEBUG_OBJECT (qtdemux,
13335               "Have VOBSUB palette. Creating palette event");
13336           /* move to decConfigDescr data and read palette */
13337           data = ptr;
13338           for (i = 0; i < 16; i++) {
13339             clut[i] = QT_UINT32 (data);
13340             data += 4;
13341           }
13342
13343           s = gst_structure_new ("application/x-gst-dvd", "event",
13344               G_TYPE_STRING, "dvd-spu-clut-change",
13345               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13346               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13347               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13348               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13349               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13350               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13351               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13352               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13353               NULL);
13354
13355           /* store event and trigger custom processing */
13356           stream->pending_event =
13357               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13358         } else {
13359           /* Generic codec_data handler puts it on the caps */
13360           data_ptr = ptr;
13361           data_len = len;
13362         }
13363
13364         ptr += len;
13365         break;
13366       case SL_CONFIG_DESC_TAG:
13367         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13368         ptr += 1;
13369         break;
13370       default:
13371         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13372             tag);
13373         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13374         ptr += len;
13375         break;
13376     }
13377   }
13378
13379   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13380    * in use, and should also be used to override some other parameters for some
13381    * codecs. */
13382   switch (object_type_id) {
13383     case 0x20:                 /* MPEG-4 */
13384       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13385        * profile_and_level_indication */
13386       if (data_ptr != NULL && data_len >= 5 &&
13387           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13388         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13389             data_ptr + 4, data_len - 4);
13390       }
13391       break;                    /* Nothing special needed here */
13392     case 0x21:                 /* H.264 */
13393       codec_name = "H.264 / AVC";
13394       caps = gst_caps_new_simple ("video/x-h264",
13395           "stream-format", G_TYPE_STRING, "avc",
13396           "alignment", G_TYPE_STRING, "au", NULL);
13397       break;
13398     case 0x40:                 /* AAC (any) */
13399     case 0x66:                 /* AAC Main */
13400     case 0x67:                 /* AAC LC */
13401     case 0x68:                 /* AAC SSR */
13402       /* Override channels and rate based on the codec_data, as it's often
13403        * wrong. */
13404       /* Only do so for basic setup without HE-AAC extension */
13405       if (data_ptr && data_len == 2) {
13406         guint channels, rate;
13407
13408         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13409         if (channels > 0)
13410           entry->n_channels = channels;
13411
13412         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13413         if (rate > 0)
13414           entry->rate = rate;
13415       }
13416
13417       /* Set level and profile if possible */
13418       if (data_ptr != NULL && data_len >= 2) {
13419         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13420             data_ptr, data_len);
13421       } else {
13422         const gchar *profile_str = NULL;
13423         GstBuffer *buffer;
13424         GstMapInfo map;
13425         guint8 *codec_data;
13426         gint rate_idx, profile;
13427
13428         /* No codec_data, let's invent something.
13429          * FIXME: This is wrong for SBR! */
13430
13431         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13432
13433         buffer = gst_buffer_new_and_alloc (2);
13434         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13435         codec_data = map.data;
13436
13437         rate_idx =
13438             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13439             (stream)->rate);
13440
13441         switch (object_type_id) {
13442           case 0x66:
13443             profile_str = "main";
13444             profile = 0;
13445             break;
13446           case 0x67:
13447             profile_str = "lc";
13448             profile = 1;
13449             break;
13450           case 0x68:
13451             profile_str = "ssr";
13452             profile = 2;
13453             break;
13454           default:
13455             profile = 3;
13456             break;
13457         }
13458
13459         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13460         codec_data[1] =
13461             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13462
13463         gst_buffer_unmap (buffer, &map);
13464         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13465             GST_TYPE_BUFFER, buffer, NULL);
13466         gst_buffer_unref (buffer);
13467
13468         if (profile_str) {
13469           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13470               G_TYPE_STRING, profile_str, NULL);
13471         }
13472       }
13473       break;
13474     case 0x60:                 /* MPEG-2, various profiles */
13475     case 0x61:
13476     case 0x62:
13477     case 0x63:
13478     case 0x64:
13479     case 0x65:
13480       codec_name = "MPEG-2 video";
13481       caps = gst_caps_new_simple ("video/mpeg",
13482           "mpegversion", G_TYPE_INT, 2,
13483           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13484       break;
13485     case 0x69:                 /* MPEG-2 BC audio */
13486     case 0x6B:                 /* MPEG-1 audio */
13487       caps = gst_caps_new_simple ("audio/mpeg",
13488           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13489       codec_name = "MPEG-1 audio";
13490       break;
13491     case 0x6A:                 /* MPEG-1 */
13492       codec_name = "MPEG-1 video";
13493       caps = gst_caps_new_simple ("video/mpeg",
13494           "mpegversion", G_TYPE_INT, 1,
13495           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13496       break;
13497     case 0x6C:                 /* MJPEG */
13498       caps =
13499           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13500           NULL);
13501       codec_name = "Motion-JPEG";
13502       break;
13503     case 0x6D:                 /* PNG */
13504       caps =
13505           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13506           NULL);
13507       codec_name = "PNG still images";
13508       break;
13509     case 0x6E:                 /* JPEG2000 */
13510       codec_name = "JPEG-2000";
13511       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13512       break;
13513     case 0xA4:                 /* Dirac */
13514       codec_name = "Dirac";
13515       caps = gst_caps_new_empty_simple ("video/x-dirac");
13516       break;
13517     case 0xA5:                 /* AC3 */
13518       codec_name = "AC-3 audio";
13519       caps = gst_caps_new_simple ("audio/x-ac3",
13520           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13521       break;
13522     case 0xA9:                 /* AC3 */
13523       codec_name = "DTS audio";
13524       caps = gst_caps_new_simple ("audio/x-dts",
13525           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13526       break;
13527     case 0xE1:                 /* QCELP */
13528       /* QCELP, the codec_data is a riff tag (little endian) with
13529        * 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). */
13530       caps = gst_caps_new_empty_simple ("audio/qcelp");
13531       codec_name = "QCELP";
13532       break;
13533     default:
13534       break;
13535   }
13536
13537   /* If we have a replacement caps, then change our caps for this stream */
13538   if (caps) {
13539     gst_caps_unref (entry->caps);
13540     entry->caps = caps;
13541   }
13542
13543   if (codec_name && list)
13544     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13545         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13546
13547   /* Add the codec_data attribute to caps, if we have it */
13548   if (data_ptr) {
13549     GstBuffer *buffer;
13550
13551     buffer = gst_buffer_new_and_alloc (data_len);
13552     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13553
13554     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13555     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13556
13557     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13558         buffer, NULL);
13559     gst_buffer_unref (buffer);
13560   }
13561
13562 }
13563
13564 static inline GstCaps *
13565 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13566 {
13567   GstCaps *caps;
13568   guint i;
13569   char *s, fourstr[5];
13570
13571   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13572   for (i = 0; i < 4; i++) {
13573     if (!g_ascii_isalnum (fourstr[i]))
13574       fourstr[i] = '_';
13575   }
13576   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13577   caps = gst_caps_new_empty_simple (s);
13578   g_free (s);
13579   return caps;
13580 }
13581
13582 #define _codec(name) \
13583   do { \
13584     if (codec_name) { \
13585       *codec_name = g_strdup (name); \
13586     } \
13587   } while (0)
13588
13589 static GstCaps *
13590 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13591     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13592     const guint8 * stsd_entry_data, gchar ** codec_name)
13593 {
13594   GstCaps *caps = NULL;
13595   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13596
13597   switch (fourcc) {
13598     case FOURCC_png:
13599       _codec ("PNG still images");
13600       caps = gst_caps_new_empty_simple ("image/png");
13601       break;
13602     case FOURCC_jpeg:
13603       _codec ("JPEG still images");
13604       caps =
13605           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13606           NULL);
13607       break;
13608     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13609     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13610     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13611     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13612       _codec ("Motion-JPEG");
13613       caps =
13614           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13615           NULL);
13616       break;
13617     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13618       _codec ("Motion-JPEG format B");
13619       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13620       break;
13621     case FOURCC_mjp2:
13622       _codec ("JPEG-2000");
13623       /* override to what it should be according to spec, avoid palette_data */
13624       entry->bits_per_sample = 24;
13625       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13626       break;
13627     case FOURCC_SVQ3:
13628       _codec ("Sorensen video v.3");
13629       caps = gst_caps_new_simple ("video/x-svq",
13630           "svqversion", G_TYPE_INT, 3, NULL);
13631       break;
13632     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13633     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13634       _codec ("Sorensen video v.1");
13635       caps = gst_caps_new_simple ("video/x-svq",
13636           "svqversion", G_TYPE_INT, 1, NULL);
13637       break;
13638     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13639       caps = gst_caps_new_empty_simple ("video/x-raw");
13640       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13641       _codec ("Windows Raw RGB");
13642       stream->alignment = 32;
13643       break;
13644     case FOURCC_raw_:
13645     {
13646       guint16 bps;
13647
13648       bps = QT_UINT16 (stsd_entry_data + 82);
13649       switch (bps) {
13650         case 15:
13651           format = GST_VIDEO_FORMAT_RGB15;
13652           break;
13653         case 16:
13654           format = GST_VIDEO_FORMAT_RGB16;
13655           break;
13656         case 24:
13657           format = GST_VIDEO_FORMAT_RGB;
13658           break;
13659         case 32:
13660           format = GST_VIDEO_FORMAT_ARGB;
13661           break;
13662         default:
13663           /* unknown */
13664           break;
13665       }
13666       break;
13667     }
13668     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13669       format = GST_VIDEO_FORMAT_I420;
13670       break;
13671     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13672     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13673       format = GST_VIDEO_FORMAT_I420;
13674       break;
13675     case FOURCC_2vuy:
13676     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13677       format = GST_VIDEO_FORMAT_UYVY;
13678       break;
13679     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13680       format = GST_VIDEO_FORMAT_v308;
13681       break;
13682     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13683       format = GST_VIDEO_FORMAT_v216;
13684       break;
13685     case FOURCC_v210:
13686       format = GST_VIDEO_FORMAT_v210;
13687       break;
13688     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13689       format = GST_VIDEO_FORMAT_r210;
13690       break;
13691       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13692          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13693          format = GST_VIDEO_FORMAT_v410;
13694          break;
13695        */
13696       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13697        * but different order than AYUV
13698        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13699        format = GST_VIDEO_FORMAT_v408;
13700        break;
13701        */
13702     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13703     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13704       _codec ("MPEG-1 video");
13705       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13706           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13707       break;
13708     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13709     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13710     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13711     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13712     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13713     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13714     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13715     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13716     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13717     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13718     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13719     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13720     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13721     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13722     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13723     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13724     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13725     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13726     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13727     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13728     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13729     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13730     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13731     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13732     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13733     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13734     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13735     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13736     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13737     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13738     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13739     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13740     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13741     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13742     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13743     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13744     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13745     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13746     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13747     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13748     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13749     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13750     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13751     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13752     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13753     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13754     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13755       _codec ("MPEG-2 video");
13756       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13757           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13758       break;
13759     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13760       _codec ("GIF still images");
13761       caps = gst_caps_new_empty_simple ("image/gif");
13762       break;
13763     case FOURCC_h263:
13764     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13765     case FOURCC_s263:
13766     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13767       _codec ("H.263");
13768       /* ffmpeg uses the height/width props, don't know why */
13769       caps = gst_caps_new_simple ("video/x-h263",
13770           "variant", G_TYPE_STRING, "itu", NULL);
13771       break;
13772     case FOURCC_mp4v:
13773     case FOURCC_MP4V:
13774       _codec ("MPEG-4 video");
13775       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13776           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13777       break;
13778     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13779     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13780       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13781       caps = gst_caps_new_simple ("video/x-msmpeg",
13782           "msmpegversion", G_TYPE_INT, 43, NULL);
13783       break;
13784     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13785       _codec ("DivX 3");
13786       caps = gst_caps_new_simple ("video/x-divx",
13787           "divxversion", G_TYPE_INT, 3, NULL);
13788       break;
13789     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13790     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13791       _codec ("DivX 4");
13792       caps = gst_caps_new_simple ("video/x-divx",
13793           "divxversion", G_TYPE_INT, 4, NULL);
13794       break;
13795     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13796       _codec ("DivX 5");
13797       caps = gst_caps_new_simple ("video/x-divx",
13798           "divxversion", G_TYPE_INT, 5, NULL);
13799       break;
13800
13801     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13802       _codec ("FFV1");
13803       caps = gst_caps_new_simple ("video/x-ffv",
13804           "ffvversion", G_TYPE_INT, 1, NULL);
13805       break;
13806
13807     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13808     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13809     case FOURCC_XVID:
13810     case FOURCC_xvid:
13811     case FOURCC_FMP4:
13812     case FOURCC_fmp4:
13813     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13814       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13815           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13816       _codec ("MPEG-4");
13817       break;
13818
13819     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13820       _codec ("Cinepak");
13821       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13822       break;
13823     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13824       _codec ("Apple QuickDraw");
13825       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13826       break;
13827     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13828       _codec ("Apple video");
13829       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13830       break;
13831     case FOURCC_H264:
13832     case FOURCC_avc1:
13833       _codec ("H.264 / AVC");
13834       caps = gst_caps_new_simple ("video/x-h264",
13835           "stream-format", G_TYPE_STRING, "avc",
13836           "alignment", G_TYPE_STRING, "au", NULL);
13837       break;
13838     case FOURCC_avc3:
13839       _codec ("H.264 / AVC");
13840       caps = gst_caps_new_simple ("video/x-h264",
13841           "stream-format", G_TYPE_STRING, "avc3",
13842           "alignment", G_TYPE_STRING, "au", NULL);
13843       break;
13844     case FOURCC_H265:
13845     case FOURCC_hvc1:
13846       _codec ("H.265 / HEVC");
13847       caps = gst_caps_new_simple ("video/x-h265",
13848           "stream-format", G_TYPE_STRING, "hvc1",
13849           "alignment", G_TYPE_STRING, "au", NULL);
13850       break;
13851     case FOURCC_hev1:
13852       _codec ("H.265 / HEVC");
13853       caps = gst_caps_new_simple ("video/x-h265",
13854           "stream-format", G_TYPE_STRING, "hev1",
13855           "alignment", G_TYPE_STRING, "au", NULL);
13856       break;
13857     case FOURCC_rle_:
13858       _codec ("Run-length encoding");
13859       caps = gst_caps_new_simple ("video/x-rle",
13860           "layout", G_TYPE_STRING, "quicktime", NULL);
13861       break;
13862     case FOURCC_WRLE:
13863       _codec ("Run-length encoding");
13864       caps = gst_caps_new_simple ("video/x-rle",
13865           "layout", G_TYPE_STRING, "microsoft", NULL);
13866       break;
13867     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13868     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13869       _codec ("Indeo Video 3");
13870       caps = gst_caps_new_simple ("video/x-indeo",
13871           "indeoversion", G_TYPE_INT, 3, NULL);
13872       break;
13873     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13874     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13875       _codec ("Intel Video 4");
13876       caps = gst_caps_new_simple ("video/x-indeo",
13877           "indeoversion", G_TYPE_INT, 4, NULL);
13878       break;
13879     case FOURCC_dvcp:
13880     case FOURCC_dvc_:
13881     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13882     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13883     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13884     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13885     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13886     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13887       _codec ("DV Video");
13888       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13889           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13890       break;
13891     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13892     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13893       _codec ("DVCPro50 Video");
13894       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13895           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13896       break;
13897     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13898     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13899       _codec ("DVCProHD Video");
13900       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13901           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13902       break;
13903     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13904       _codec ("Apple Graphics (SMC)");
13905       caps = gst_caps_new_empty_simple ("video/x-smc");
13906       break;
13907     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13908       _codec ("VP3");
13909       caps = gst_caps_new_empty_simple ("video/x-vp3");
13910       break;
13911     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13912       _codec ("VP6 Flash");
13913       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13914       break;
13915     case FOURCC_XiTh:
13916       _codec ("Theora");
13917       caps = gst_caps_new_empty_simple ("video/x-theora");
13918       /* theora uses one byte of padding in the data stream because it does not
13919        * allow 0 sized packets while theora does */
13920       entry->padding = 1;
13921       break;
13922     case FOURCC_drac:
13923       _codec ("Dirac");
13924       caps = gst_caps_new_empty_simple ("video/x-dirac");
13925       break;
13926     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13927       _codec ("TIFF still images");
13928       caps = gst_caps_new_empty_simple ("image/tiff");
13929       break;
13930     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13931       _codec ("Apple Intermediate Codec");
13932       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13933       break;
13934     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13935       _codec ("AVID DNxHD");
13936       caps = gst_caps_from_string ("video/x-dnxhd");
13937       break;
13938     case FOURCC_VP80:
13939       _codec ("On2 VP8");
13940       caps = gst_caps_from_string ("video/x-vp8");
13941       break;
13942     case FOURCC_apcs:
13943       _codec ("Apple ProRes LT");
13944       caps =
13945           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13946           NULL);
13947       break;
13948     case FOURCC_apch:
13949       _codec ("Apple ProRes HQ");
13950       caps =
13951           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13952           NULL);
13953       break;
13954     case FOURCC_apcn:
13955       _codec ("Apple ProRes");
13956       caps =
13957           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13958           "standard", NULL);
13959       break;
13960     case FOURCC_apco:
13961       _codec ("Apple ProRes Proxy");
13962       caps =
13963           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13964           "proxy", NULL);
13965       break;
13966     case FOURCC_ap4h:
13967       _codec ("Apple ProRes 4444");
13968       caps =
13969           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13970           "4444", NULL);
13971       break;
13972     case FOURCC_ap4x:
13973       _codec ("Apple ProRes 4444 XQ");
13974       caps =
13975           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13976           "4444xq", NULL);
13977       break;
13978     case FOURCC_cfhd:
13979       _codec ("GoPro CineForm");
13980       caps = gst_caps_from_string ("video/x-cineform");
13981       break;
13982     case FOURCC_vc_1:
13983     case FOURCC_ovc1:
13984       _codec ("VC-1");
13985       caps = gst_caps_new_simple ("video/x-wmv",
13986           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13987       break;
13988     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13989     default:
13990     {
13991       caps = _get_unknown_codec_name ("video", fourcc);
13992       break;
13993     }
13994   }
13995
13996   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13997     GstVideoInfo info;
13998
13999     gst_video_info_init (&info);
14000     gst_video_info_set_format (&info, format, entry->width, entry->height);
14001
14002     caps = gst_video_info_to_caps (&info);
14003     *codec_name = gst_pb_utils_get_codec_description (caps);
14004
14005     /* enable clipping for raw video streams */
14006     stream->need_clip = TRUE;
14007     stream->alignment = 32;
14008   }
14009
14010   return caps;
14011 }
14012
14013 static guint
14014 round_up_pow2 (guint n)
14015 {
14016   n = n - 1;
14017   n = n | (n >> 1);
14018   n = n | (n >> 2);
14019   n = n | (n >> 4);
14020   n = n | (n >> 8);
14021   n = n | (n >> 16);
14022   return n + 1;
14023 }
14024
14025 static GstCaps *
14026 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14027     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14028     int len, gchar ** codec_name)
14029 {
14030   GstCaps *caps;
14031   const GstStructure *s;
14032   const gchar *name;
14033   gint endian = 0;
14034   GstAudioFormat format = 0;
14035   gint depth;
14036
14037   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14038
14039   depth = entry->bytes_per_packet * 8;
14040
14041   switch (fourcc) {
14042     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14043     case FOURCC_raw_:
14044       /* 8-bit audio is unsigned */
14045       if (depth == 8)
14046         format = GST_AUDIO_FORMAT_U8;
14047       /* otherwise it's signed and big-endian just like 'twos' */
14048     case FOURCC_twos:
14049       endian = G_BIG_ENDIAN;
14050       /* fall-through */
14051     case FOURCC_sowt:
14052     {
14053       gchar *str;
14054
14055       if (!endian)
14056         endian = G_LITTLE_ENDIAN;
14057
14058       if (!format)
14059         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14060
14061       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14062       _codec (str);
14063       g_free (str);
14064
14065       caps = gst_caps_new_simple ("audio/x-raw",
14066           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14067           "layout", G_TYPE_STRING, "interleaved", NULL);
14068       stream->alignment = GST_ROUND_UP_8 (depth);
14069       stream->alignment = round_up_pow2 (stream->alignment);
14070       break;
14071     }
14072     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14073       _codec ("Raw 64-bit floating-point audio");
14074       caps = gst_caps_new_simple ("audio/x-raw",
14075           "format", G_TYPE_STRING, "F64BE",
14076           "layout", G_TYPE_STRING, "interleaved", NULL);
14077       stream->alignment = 8;
14078       break;
14079     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14080       _codec ("Raw 32-bit floating-point audio");
14081       caps = gst_caps_new_simple ("audio/x-raw",
14082           "format", G_TYPE_STRING, "F32BE",
14083           "layout", G_TYPE_STRING, "interleaved", NULL);
14084       stream->alignment = 4;
14085       break;
14086     case FOURCC_in24:
14087       _codec ("Raw 24-bit PCM audio");
14088       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14089        * endian later */
14090       caps = gst_caps_new_simple ("audio/x-raw",
14091           "format", G_TYPE_STRING, "S24BE",
14092           "layout", G_TYPE_STRING, "interleaved", NULL);
14093       stream->alignment = 4;
14094       break;
14095     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14096       _codec ("Raw 32-bit PCM audio");
14097       caps = gst_caps_new_simple ("audio/x-raw",
14098           "format", G_TYPE_STRING, "S32BE",
14099           "layout", G_TYPE_STRING, "interleaved", NULL);
14100       stream->alignment = 4;
14101       break;
14102     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14103       _codec ("Raw 16-bit PCM audio");
14104       caps = gst_caps_new_simple ("audio/x-raw",
14105           "format", G_TYPE_STRING, "S16LE",
14106           "layout", G_TYPE_STRING, "interleaved", NULL);
14107       stream->alignment = 2;
14108       break;
14109     case FOURCC_ulaw:
14110       _codec ("Mu-law audio");
14111       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14112       break;
14113     case FOURCC_alaw:
14114       _codec ("A-law audio");
14115       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14116       break;
14117     case 0x0200736d:
14118     case 0x6d730002:
14119       _codec ("Microsoft ADPCM");
14120       /* Microsoft ADPCM-ACM code 2 */
14121       caps = gst_caps_new_simple ("audio/x-adpcm",
14122           "layout", G_TYPE_STRING, "microsoft", NULL);
14123       break;
14124     case 0x1100736d:
14125     case 0x6d730011:
14126       _codec ("DVI/IMA ADPCM");
14127       caps = gst_caps_new_simple ("audio/x-adpcm",
14128           "layout", G_TYPE_STRING, "dvi", NULL);
14129       break;
14130     case 0x1700736d:
14131     case 0x6d730017:
14132       _codec ("DVI/Intel IMA ADPCM");
14133       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14134       caps = gst_caps_new_simple ("audio/x-adpcm",
14135           "layout", G_TYPE_STRING, "quicktime", NULL);
14136       break;
14137     case 0x5500736d:
14138     case 0x6d730055:
14139       /* MPEG layer 3, CBR only (pre QT4.1) */
14140     case FOURCC__mp3:
14141       _codec ("MPEG-1 layer 3");
14142       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14143       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14144           "mpegversion", G_TYPE_INT, 1, NULL);
14145       break;
14146     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14147       _codec ("MPEG-1 layer 2");
14148       /* MPEG layer 2 */
14149       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14150           "mpegversion", G_TYPE_INT, 1, NULL);
14151       break;
14152     case 0x20736d:
14153     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14154       _codec ("EAC-3 audio");
14155       caps = gst_caps_new_simple ("audio/x-eac3",
14156           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14157       entry->sampled = TRUE;
14158       break;
14159     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14160     case FOURCC_ac_3:
14161       _codec ("AC-3 audio");
14162       caps = gst_caps_new_simple ("audio/x-ac3",
14163           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14164       entry->sampled = TRUE;
14165       break;
14166     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14167     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14168       _codec ("DTS audio");
14169       caps = gst_caps_new_simple ("audio/x-dts",
14170           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14171       entry->sampled = TRUE;
14172       break;
14173     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14174     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14175       _codec ("DTS-HD audio");
14176       caps = gst_caps_new_simple ("audio/x-dts",
14177           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14178       entry->sampled = TRUE;
14179       break;
14180     case FOURCC_MAC3:
14181       _codec ("MACE-3");
14182       caps = gst_caps_new_simple ("audio/x-mace",
14183           "maceversion", G_TYPE_INT, 3, NULL);
14184       break;
14185     case FOURCC_MAC6:
14186       _codec ("MACE-6");
14187       caps = gst_caps_new_simple ("audio/x-mace",
14188           "maceversion", G_TYPE_INT, 6, NULL);
14189       break;
14190     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14191       /* ogg/vorbis */
14192       caps = gst_caps_new_empty_simple ("application/ogg");
14193       break;
14194     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14195       _codec ("DV audio");
14196       caps = gst_caps_new_empty_simple ("audio/x-dv");
14197       break;
14198     case FOURCC_mp4a:
14199       _codec ("MPEG-4 AAC audio");
14200       caps = gst_caps_new_simple ("audio/mpeg",
14201           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14202           "stream-format", G_TYPE_STRING, "raw", NULL);
14203       break;
14204     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14205       _codec ("QDesign Music");
14206       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14207       break;
14208     case FOURCC_QDM2:
14209       _codec ("QDesign Music v.2");
14210       /* FIXME: QDesign music version 2 (no constant) */
14211       if (FALSE && data) {
14212         caps = gst_caps_new_simple ("audio/x-qdm2",
14213             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14214             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14215             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14216       } else {
14217         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14218       }
14219       break;
14220     case FOURCC_agsm:
14221       _codec ("GSM audio");
14222       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14223       break;
14224     case FOURCC_samr:
14225       _codec ("AMR audio");
14226       caps = gst_caps_new_empty_simple ("audio/AMR");
14227       break;
14228     case FOURCC_sawb:
14229       _codec ("AMR-WB audio");
14230       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14231       break;
14232     case FOURCC_ima4:
14233       _codec ("Quicktime IMA ADPCM");
14234       caps = gst_caps_new_simple ("audio/x-adpcm",
14235           "layout", G_TYPE_STRING, "quicktime", NULL);
14236       break;
14237     case FOURCC_alac:
14238       _codec ("Apple lossless audio");
14239       caps = gst_caps_new_empty_simple ("audio/x-alac");
14240       break;
14241     case FOURCC_fLaC:
14242       _codec ("Free Lossless Audio Codec");
14243       caps = gst_caps_new_simple ("audio/x-flac",
14244           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14245       break;
14246     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14247       _codec ("QualComm PureVoice");
14248       caps = gst_caps_from_string ("audio/qcelp");
14249       break;
14250     case FOURCC_wma_:
14251     case FOURCC_owma:
14252       _codec ("WMA");
14253       caps = gst_caps_new_empty_simple ("audio/x-wma");
14254       break;
14255     case FOURCC_opus:
14256       _codec ("Opus");
14257       caps = gst_caps_new_empty_simple ("audio/x-opus");
14258       break;
14259     case FOURCC_lpcm:
14260     {
14261       guint32 flags = 0;
14262       guint32 depth = 0;
14263       guint32 width = 0;
14264       GstAudioFormat format;
14265       enum
14266       {
14267         FLAG_IS_FLOAT = 0x1,
14268         FLAG_IS_BIG_ENDIAN = 0x2,
14269         FLAG_IS_SIGNED = 0x4,
14270         FLAG_IS_PACKED = 0x8,
14271         FLAG_IS_ALIGNED_HIGH = 0x10,
14272         FLAG_IS_NON_INTERLEAVED = 0x20
14273       };
14274       _codec ("Raw LPCM audio");
14275
14276       if (data && len >= 36) {
14277         depth = QT_UINT32 (data + 24);
14278         flags = QT_UINT32 (data + 28);
14279         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14280       }
14281       if ((flags & FLAG_IS_FLOAT) == 0) {
14282         if (depth == 0)
14283           depth = 16;
14284         if (width == 0)
14285           width = 16;
14286         if ((flags & FLAG_IS_ALIGNED_HIGH))
14287           depth = width;
14288
14289         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14290             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14291             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14292         caps = gst_caps_new_simple ("audio/x-raw",
14293             "format", G_TYPE_STRING,
14294             format !=
14295             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14296             "UNKNOWN", "layout", G_TYPE_STRING,
14297             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14298             "interleaved", NULL);
14299         stream->alignment = GST_ROUND_UP_8 (depth);
14300         stream->alignment = round_up_pow2 (stream->alignment);
14301       } else {
14302         if (width == 0)
14303           width = 32;
14304         if (width == 64) {
14305           if (flags & FLAG_IS_BIG_ENDIAN)
14306             format = GST_AUDIO_FORMAT_F64BE;
14307           else
14308             format = GST_AUDIO_FORMAT_F64LE;
14309         } else {
14310           if (flags & FLAG_IS_BIG_ENDIAN)
14311             format = GST_AUDIO_FORMAT_F32BE;
14312           else
14313             format = GST_AUDIO_FORMAT_F32LE;
14314         }
14315         caps = gst_caps_new_simple ("audio/x-raw",
14316             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14317             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14318             "non-interleaved" : "interleaved", NULL);
14319         stream->alignment = width / 8;
14320       }
14321       break;
14322     }
14323     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14324       /* ? */
14325     default:
14326     {
14327       caps = _get_unknown_codec_name ("audio", fourcc);
14328       break;
14329     }
14330   }
14331
14332   if (caps) {
14333     GstCaps *templ_caps =
14334         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14335     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14336     gst_caps_unref (caps);
14337     gst_caps_unref (templ_caps);
14338     caps = intersection;
14339   }
14340
14341   /* enable clipping for raw audio streams */
14342   s = gst_caps_get_structure (caps, 0);
14343   name = gst_structure_get_name (s);
14344   if (g_str_has_prefix (name, "audio/x-raw")) {
14345     stream->need_clip = TRUE;
14346     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14347     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14348   }
14349   return caps;
14350 }
14351
14352 static GstCaps *
14353 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14354     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14355     const guint8 * stsd_entry_data, gchar ** codec_name)
14356 {
14357   GstCaps *caps;
14358
14359   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14360
14361   switch (fourcc) {
14362     case FOURCC_mp4s:
14363       _codec ("DVD subtitle");
14364       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14365       stream->need_process = TRUE;
14366       break;
14367     case FOURCC_text:
14368       _codec ("Quicktime timed text");
14369       goto text;
14370     case FOURCC_tx3g:
14371       _codec ("3GPP timed text");
14372     text:
14373       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14374           "utf8", NULL);
14375       /* actual text piece needs to be extracted */
14376       stream->need_process = TRUE;
14377       break;
14378     case FOURCC_stpp:
14379       _codec ("XML subtitles");
14380       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14381       break;
14382     default:
14383     {
14384       caps = _get_unknown_codec_name ("text", fourcc);
14385       break;
14386     }
14387   }
14388   return caps;
14389 }
14390
14391 static GstCaps *
14392 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14393     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14394     const guint8 * stsd_entry_data, gchar ** codec_name)
14395 {
14396   GstCaps *caps;
14397
14398   switch (fourcc) {
14399     case FOURCC_m1v:
14400       _codec ("MPEG 1 video");
14401       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14402           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14403       break;
14404     default:
14405       caps = NULL;
14406       break;
14407   }
14408   return caps;
14409 }
14410
14411 static void
14412 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14413     const gchar * system_id)
14414 {
14415   gint i;
14416
14417   if (!qtdemux->protection_system_ids)
14418     qtdemux->protection_system_ids =
14419         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14420   /* Check whether we already have an entry for this system ID. */
14421   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14422     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14423     if (g_ascii_strcasecmp (system_id, id) == 0) {
14424       return;
14425     }
14426   }
14427   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14428   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14429           -1));
14430 }