419d9e3f79ca08544a71f3e9b6b7f7dd5191ec1c
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 #include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 GST_DEBUG_CATEGORY (qtdemux_debug);
104
105 typedef struct _QtDemuxSegment QtDemuxSegment;
106 typedef struct _QtDemuxSample QtDemuxSample;
107
108 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
109
110 struct _QtDemuxSample
111 {
112   guint32 size;
113   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
114   guint64 offset;
115   guint64 timestamp;            /* DTS In mov time */
116   guint32 duration;             /* In mov time */
117   gboolean keyframe;            /* TRUE when this packet is a keyframe */
118 };
119
120 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
121 typedef struct _QtDemuxSphericalMetadata QtDemuxSphericalMetadata;
122
123 struct _QtDemuxSphericalMetadata
124 {
125   gboolean is_spherical;
126   gboolean is_stitched;
127   char *stitching_software;
128   char *projection_type;
129   char *stereo_mode;
130   int source_count;
131   int init_view_heading;
132   int init_view_pitch;
133   int init_view_roll;
134   int timestamp;
135   int full_pano_width_pixels;
136   int full_pano_height_pixels;
137   int cropped_area_image_width;
138   int cropped_area_image_height;
139   int cropped_area_left;
140   int cropped_area_top;
141   QTDEMUX_AMBISONIC_TYPE ambisonic_type;
142   QTDEMUX_AMBISONIC_FORMAT ambisonic_format;
143   QTDEMUX_AMBISONIC_ORDER ambisonic_order;
144 };
145
146 QtDemuxSphericalMetadata *spherical_metadata;
147 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
148
149 /* Macros for converting to/from timescale */
150 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
151 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
152
153 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
154 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
155
156 /* timestamp is the DTS */
157 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
158 /* timestamp + offset + cslg_shift is the outgoing PTS */
159 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
160 /* timestamp + offset is the PTS used for internal seek calcuations */
161 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
162 /* timestamp + duration - dts is the duration */
163 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
164
165 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
166
167 /*
168  * Quicktime has tracks and segments. A track is a continuous piece of
169  * multimedia content. The track is not always played from start to finish but
170  * instead, pieces of the track are 'cut out' and played in sequence. This is
171  * what the segments do.
172  *
173  * Inside the track we have keyframes (K) and delta frames. The track has its
174  * own timing, which starts from 0 and extends to end. The position in the track
175  * is called the media_time.
176  *
177  * The segments now describe the pieces that should be played from this track
178  * and are basically tuples of media_time/duration/rate entries. We can have
179  * multiple segments and they are all played after one another. An example:
180  *
181  * segment 1: media_time: 1 second, duration: 1 second, rate 1
182  * segment 2: media_time: 3 second, duration: 2 second, rate 2
183  *
184  * To correctly play back this track, one must play: 1 second of media starting
185  * from media_time 1 followed by 2 seconds of media starting from media_time 3
186  * at a rate of 2.
187  *
188  * Each of the segments will be played at a specific time, the first segment at
189  * time 0, the second one after the duration of the first one, etc.. Note that
190  * the time in resulting playback is not identical to the media_time of the
191  * track anymore.
192  *
193  * Visually, assuming the track has 4 second of media_time:
194  *
195  *                (a)                   (b)          (c)              (d)
196  *         .-----------------------------------------------------------.
197  * track:  | K.....K.........K........K.......K.......K...........K... |
198  *         '-----------------------------------------------------------'
199  *         0              1              2              3              4
200  *           .------------^              ^   .----------^              ^
201  *          /              .-------------'  /       .------------------'
202  *         /              /          .-----'       /
203  *         .--------------.         .--------------.
204  *         | segment 1    |         | segment 2    |
205  *         '--------------'         '--------------'
206  *
207  * The challenge here is to cut out the right pieces of the track for each of
208  * the playback segments. This fortunately can easily be done with the SEGMENT
209  * events of GStreamer.
210  *
211  * For playback of segment 1, we need to provide the decoder with the keyframe
212  * (a), in the above figure, but we must instruct it only to output the decoded
213  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
214  * position set to the time of the segment: 0.
215  *
216  * We then proceed to push data from keyframe (a) to frame (b). The decoder
217  * decodes but clips all before media_time 1.
218  *
219  * After finishing a segment, we push out a new SEGMENT event with the clipping
220  * boundaries of the new data.
221  *
222  * This is a good usecase for the GStreamer accumulated SEGMENT events.
223  */
224
225 struct _QtDemuxSegment
226 {
227   /* global time and duration, all gst time */
228   GstClockTime time;
229   GstClockTime stop_time;
230   GstClockTime duration;
231   /* media time of trak, all gst time */
232   GstClockTime media_start;
233   GstClockTime media_stop;
234   gdouble rate;
235   /* Media start time in trak timescale units */
236   guint32 trak_media_start;
237 };
238
239 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
240
241 /* Used with fragmented MP4 files (mfra atom) */
242 typedef struct
243 {
244   GstClockTime ts;
245   guint64 moof_offset;
246 } QtDemuxRandomAccessEntry;
247
248 typedef struct _QtDemuxStreamStsdEntry
249 {
250   GstCaps *caps;
251   guint32 fourcc;
252   gboolean sparse;
253
254   /* video info */
255   gint width;
256   gint height;
257   gint par_w;
258   gint par_h;
259   /* Numerator/denominator framerate */
260   gint fps_n;
261   gint fps_d;
262   GstVideoColorimetry colorimetry;
263   guint16 bits_per_sample;
264   guint16 color_table_id;
265   GstMemory *rgb8_palette;
266   guint interlace_mode;
267   guint field_order;
268
269   /* audio info */
270   gdouble rate;
271   gint n_channels;
272   guint samples_per_packet;
273   guint samples_per_frame;
274   guint bytes_per_packet;
275   guint bytes_per_sample;
276   guint bytes_per_frame;
277   guint compression;
278
279   /* if we use chunks or samples */
280   gboolean sampled;
281   guint padding;
282
283 } QtDemuxStreamStsdEntry;
284
285 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
286
287 struct _QtDemuxStream
288 {
289   GstPad *pad;
290
291   QtDemuxStreamStsdEntry *stsd_entries;
292   guint stsd_entries_length;
293   guint cur_stsd_entry_index;
294
295   /* stream type */
296   guint32 subtype;
297
298   gboolean new_caps;            /* If TRUE, caps need to be generated (by
299                                  * calling _configure_stream()) This happens
300                                  * for MSS and fragmented streams */
301
302   gboolean new_stream;          /* signals that a stream_start is required */
303   gboolean on_keyframe;         /* if this stream last pushed buffer was a
304                                  * keyframe. This is important to identify
305                                  * where to stop pushing buffers after a
306                                  * segment stop time */
307
308   /* if the stream has a redirect URI in its headers, we store it here */
309   gchar *redirect_uri;
310
311   /* track id */
312   guint track_id;
313
314   /* duration/scale */
315   guint64 duration;             /* in timescale units */
316   guint32 timescale;
317
318   /* language */
319   gchar lang_id[4];             /* ISO 639-2T language code */
320
321   /* our samples */
322   guint32 n_samples;
323   QtDemuxSample *samples;
324   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
325   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
326                                    the framerate */
327   guint32 n_samples_moof;       /* sample count in a moof */
328   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
329                                  * the framerate of fragmented format stream */
330   guint64 duration_last_moof;
331
332   guint32 offset_in_sample;     /* Offset in the current sample, used for
333                                  * streams which have got exceedingly big
334                                  * sample size (such as 24s of raw audio).
335                                  * Only used when max_buffer_size is non-NULL */
336   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
337                                  * Currently only set for raw audio streams*/
338
339   /* video info */
340   /* aspect ratio */
341   gint display_width;
342   gint display_height;
343
344   /* allocation */
345   gboolean use_allocator;
346   GstAllocator *allocator;
347   GstAllocationParams params;
348
349   gsize alignment;
350
351   /* when a discontinuity is pending */
352   gboolean discont;
353
354   /* list of buffers to push first */
355   GSList *buffers;
356
357   /* if we need to clip this buffer. This is only needed for uncompressed
358    * data */
359   gboolean need_clip;
360
361   /* buffer needs some custom processing, e.g. subtitles */
362   gboolean need_process;
363
364   /* current position */
365   guint32 segment_index;
366   guint32 sample_index;
367   GstClockTime time_position;   /* in gst time */
368   guint64 accumulated_base;
369
370   /* the Gst segment we are processing out, used for clipping */
371   GstSegment segment;
372
373   /* quicktime segments */
374   guint32 n_segments;
375   QtDemuxSegment *segments;
376   gboolean dummy_segment;
377   guint32 from_sample;
378   guint32 to_sample;
379
380   gboolean sent_eos;
381   GstTagList *stream_tags;
382   gboolean send_global_tags;
383
384   GstEvent *pending_event;
385
386   GstByteReader stco;
387   GstByteReader stsz;
388   GstByteReader stsc;
389   GstByteReader stts;
390   GstByteReader stss;
391   GstByteReader stps;
392   GstByteReader ctts;
393
394   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
395   gint64 stbl_index;
396   /* stco */
397   guint co_size;
398   GstByteReader co_chunk;
399   guint32 first_chunk;
400   guint32 current_chunk;
401   guint32 last_chunk;
402   guint32 samples_per_chunk;
403   guint32 stsd_sample_description_id;
404   guint32 stco_sample_index;
405   /* stsz */
406   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
407   /* stsc */
408   guint32 stsc_index;
409   guint32 n_samples_per_chunk;
410   guint32 stsc_chunk_index;
411   guint32 stsc_sample_index;
412   guint64 chunk_offset;
413   /* stts */
414   guint32 stts_index;
415   guint32 stts_samples;
416   guint32 n_sample_times;
417   guint32 stts_sample_index;
418   guint64 stts_time;
419   guint32 stts_duration;
420   /* stss */
421   gboolean stss_present;
422   guint32 n_sample_syncs;
423   guint32 stss_index;
424   /* stps */
425   gboolean stps_present;
426   guint32 n_sample_partial_syncs;
427   guint32 stps_index;
428   QtDemuxRandomAccessEntry *ra_entries;
429   guint n_ra_entries;
430
431   const QtDemuxRandomAccessEntry *pending_seek;
432
433   /* ctts */
434   gboolean ctts_present;
435   guint32 n_composition_times;
436   guint32 ctts_index;
437   guint32 ctts_sample_index;
438   guint32 ctts_count;
439   gint32 ctts_soffset;
440
441   /* cslg */
442   guint32 cslg_shift;
443
444   /* fragmented */
445   gboolean parsed_trex;
446   guint32 def_sample_description_index; /* index is 1-based */
447   guint32 def_sample_duration;
448   guint32 def_sample_size;
449   guint32 def_sample_flags;
450
451   gboolean disabled;
452
453   /* stereoscopic video streams */
454   GstVideoMultiviewMode multiview_mode;
455   GstVideoMultiviewFlags multiview_flags;
456
457   /* protected streams */
458   gboolean protected;
459   guint32 protection_scheme_type;
460   guint32 protection_scheme_version;
461   gpointer protection_scheme_info;      /* specific to the protection scheme */
462   GQueue protection_scheme_event_queue;
463 };
464
465 /* Contains properties and cryptographic info for a set of samples from a
466  * track protected using Common Encryption (cenc) */
467 struct _QtDemuxCencSampleSetInfo
468 {
469   GstStructure *default_properties;
470
471   /* @crypto_info holds one GstStructure per sample */
472   GPtrArray *crypto_info;
473 };
474
475 static const gchar *
476 qt_demux_state_string (enum QtDemuxState state)
477 {
478   switch (state) {
479     case QTDEMUX_STATE_INITIAL:
480       return "<INITIAL>";
481     case QTDEMUX_STATE_HEADER:
482       return "<HEADER>";
483     case QTDEMUX_STATE_MOVIE:
484       return "<MOVIE>";
485     case QTDEMUX_STATE_BUFFER_MDAT:
486       return "<BUFFER_MDAT>";
487     default:
488       return "<UNKNOWN>";
489   }
490 }
491
492 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
493 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
494     guint32 fourcc, GstByteReader * parser);
495 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
496 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
497     guint32 fourcc, GstByteReader * parser);
498
499 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
500
501 static GstStaticPadTemplate gst_qtdemux_sink_template =
502     GST_STATIC_PAD_TEMPLATE ("sink",
503     GST_PAD_SINK,
504     GST_PAD_ALWAYS,
505     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
506         "application/x-3gp")
507     );
508
509 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
510 GST_STATIC_PAD_TEMPLATE ("video_%u",
511     GST_PAD_SRC,
512     GST_PAD_SOMETIMES,
513     GST_STATIC_CAPS_ANY);
514
515 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
516 GST_STATIC_PAD_TEMPLATE ("audio_%u",
517     GST_PAD_SRC,
518     GST_PAD_SOMETIMES,
519     GST_STATIC_CAPS_ANY);
520
521 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
522 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
523     GST_PAD_SRC,
524     GST_PAD_SOMETIMES,
525     GST_STATIC_CAPS_ANY);
526
527 #define gst_qtdemux_parent_class parent_class
528 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
529
530 static void gst_qtdemux_dispose (GObject * object);
531
532 static guint32
533 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
534     GstClockTime media_time);
535 static guint32
536 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
537     QtDemuxStream * str, gint64 media_offset);
538
539 #if 0
540 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
541 static GstIndex *gst_qtdemux_get_index (GstElement * element);
542 #endif
543 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
544     GstStateChange transition);
545 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
546 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
547     GstObject * parent, GstPadMode mode, gboolean active);
548
549 static void gst_qtdemux_loop (GstPad * pad);
550 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
551     GstBuffer * inbuf);
552 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
553     GstEvent * event);
554 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
555 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
556     QtDemuxStream * stream);
557 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
558     QtDemuxStream * stream);
559 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
560     gboolean force);
561
562 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
563     const guint8 * buffer, guint length);
564 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
565     const guint8 * buffer, guint length);
566 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
567 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
568     GNode * udta);
569
570 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
571     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
572     GstTagList * list);
573 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
574     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
575     const guint8 * stsd_entry_data, gchar ** codec_name);
576 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
577     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
578     const guint8 * data, int len, gchar ** codec_name);
579 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
580     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
581     gchar ** codec_name);
582 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
583     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
584     const guint8 * stsd_entry_data, gchar ** codec_name);
585
586 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
587     QtDemuxStream * stream, guint32 n);
588 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
589 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
590     QtDemuxStream * stream);
591 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
592     QtDemuxStream * stream);
593 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
594 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
595 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
596     QtDemuxStream * stream);
597 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
598     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
599 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
600     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
601     GstClockTime * _start, GstClockTime * _stop);
602 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
603     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
604
605 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
606 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
607
608 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
609
610 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
611     QtDemuxStream * stream, guint sample_index);
612 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
613     const gchar * id);
614 static void qtdemux_gst_structure_free (GstStructure * gststructure);
615
616 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
617 static void gst_tag_register_spherical_tags (void);
618 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
619
620 static void
621 gst_qtdemux_class_init (GstQTDemuxClass * klass)
622 {
623   GObjectClass *gobject_class;
624   GstElementClass *gstelement_class;
625
626   gobject_class = (GObjectClass *) klass;
627   gstelement_class = (GstElementClass *) klass;
628
629   parent_class = g_type_class_peek_parent (klass);
630
631   gobject_class->dispose = gst_qtdemux_dispose;
632
633   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
634 #if 0
635   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
636   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
637 #endif
638
639   gst_tag_register_musicbrainz_tags ();
640
641 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
642   gst_tag_register_spherical_tags ();
643 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
644
645   gst_element_class_add_static_pad_template (gstelement_class,
646       &gst_qtdemux_sink_template);
647   gst_element_class_add_static_pad_template (gstelement_class,
648       &gst_qtdemux_videosrc_template);
649   gst_element_class_add_static_pad_template (gstelement_class,
650       &gst_qtdemux_audiosrc_template);
651   gst_element_class_add_static_pad_template (gstelement_class,
652       &gst_qtdemux_subsrc_template);
653   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
654       "Codec/Demuxer",
655       "Demultiplex a QuickTime file into audio and video streams",
656       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
657
658   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
659
660 }
661
662 static void
663 gst_qtdemux_init (GstQTDemux * qtdemux)
664 {
665   qtdemux->sinkpad =
666       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
667   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
668   gst_pad_set_activatemode_function (qtdemux->sinkpad,
669       qtdemux_sink_activate_mode);
670   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
671   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
672   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
673
674   qtdemux->state = QTDEMUX_STATE_INITIAL;
675   qtdemux->pullbased = FALSE;
676   qtdemux->posted_redirect = FALSE;
677   qtdemux->neededbytes = 16;
678   qtdemux->todrop = 0;
679   qtdemux->adapter = gst_adapter_new ();
680   qtdemux->offset = 0;
681   qtdemux->first_mdat = -1;
682   qtdemux->got_moov = FALSE;
683   qtdemux->mdatoffset = -1;
684   qtdemux->mdatbuffer = NULL;
685   qtdemux->restoredata_buffer = NULL;
686   qtdemux->restoredata_offset = -1;
687   qtdemux->fragment_start = -1;
688   qtdemux->fragment_start_offset = -1;
689   qtdemux->media_caps = NULL;
690   qtdemux->exposed = FALSE;
691   qtdemux->mss_mode = FALSE;
692   qtdemux->pending_newsegment = NULL;
693   qtdemux->upstream_format_is_time = FALSE;
694   qtdemux->have_group_id = FALSE;
695   qtdemux->group_id = G_MAXUINT;
696   qtdemux->cenc_aux_info_offset = 0;
697   qtdemux->cenc_aux_info_sizes = NULL;
698   qtdemux->cenc_aux_sample_count = 0;
699   qtdemux->protection_system_ids = NULL;
700   g_queue_init (&qtdemux->protection_event_queue);
701   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
702   qtdemux->tag_list = gst_tag_list_new_empty ();
703   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
704   qtdemux->flowcombiner = gst_flow_combiner_new ();
705
706 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
707   spherical_metadata = (QtDemuxSphericalMetadata *)
708       malloc (sizeof (QtDemuxSphericalMetadata));
709
710   if (spherical_metadata) {
711     spherical_metadata->is_spherical = FALSE;
712     spherical_metadata->is_stitched = FALSE;
713     spherical_metadata->stitching_software = NULL;
714     spherical_metadata->projection_type = NULL;
715     spherical_metadata->stereo_mode = NULL;
716     spherical_metadata->source_count = 0;
717     spherical_metadata->init_view_heading = 0;
718     spherical_metadata->init_view_pitch = 0;
719     spherical_metadata->init_view_roll = 0;
720     spherical_metadata->timestamp = 0;
721     spherical_metadata->full_pano_width_pixels = 0;
722     spherical_metadata->full_pano_height_pixels = 0;
723     spherical_metadata->cropped_area_image_width = 0;
724     spherical_metadata->cropped_area_image_height = 0;
725     spherical_metadata->cropped_area_left = 0;
726     spherical_metadata->cropped_area_top = 0;
727     spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_UNKNOWN;
728     spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_TYPE_UNKNOWN;
729     spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_UNKNOWN;
730   }
731 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
732
733   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
734 }
735
736 static void
737 gst_qtdemux_dispose (GObject * object)
738 {
739   GstQTDemux *qtdemux = GST_QTDEMUX (object);
740
741 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
742   if (spherical_metadata->stitching_software)
743     free(spherical_metadata->stitching_software);
744   if (spherical_metadata->projection_type)
745     free(spherical_metadata->projection_type);
746   if (spherical_metadata->stereo_mode)
747     free(spherical_metadata->stereo_mode);
748   if (spherical_metadata)
749     free(spherical_metadata);
750 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
751
752   if (qtdemux->adapter) {
753     g_object_unref (G_OBJECT (qtdemux->adapter));
754     qtdemux->adapter = NULL;
755   }
756   gst_tag_list_unref (qtdemux->tag_list);
757   gst_flow_combiner_free (qtdemux->flowcombiner);
758   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
759       NULL);
760   g_queue_clear (&qtdemux->protection_event_queue);
761
762   g_free (qtdemux->cenc_aux_info_sizes);
763   qtdemux->cenc_aux_info_sizes = NULL;
764
765   G_OBJECT_CLASS (parent_class)->dispose (object);
766 }
767
768 static void
769 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
770 {
771   if (qtdemux->posted_redirect) {
772     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
773         (_("This file contains no playable streams.")),
774         ("no known streams found, a redirect message has been posted"));
775   } else {
776     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
777         (_("This file contains no playable streams.")),
778         ("no known streams found"));
779   }
780 }
781
782 static GstBuffer *
783 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
784 {
785   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
786       mem, size, 0, size, mem, free_func);
787 }
788
789 static GstFlowReturn
790 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
791     GstBuffer ** buf)
792 {
793   GstFlowReturn flow;
794   GstMapInfo map;
795   gsize bsize;
796
797   if (G_UNLIKELY (size == 0)) {
798     GstFlowReturn ret;
799     GstBuffer *tmp = NULL;
800
801     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
802     if (ret != GST_FLOW_OK)
803       return ret;
804
805     gst_buffer_map (tmp, &map, GST_MAP_READ);
806     size = QT_UINT32 (map.data);
807     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
808
809     gst_buffer_unmap (tmp, &map);
810     gst_buffer_unref (tmp);
811   }
812
813   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
814   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
815     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
816       /* we're pulling header but already got most interesting bits,
817        * so never mind the rest (e.g. tags) (that much) */
818       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
819           size);
820       return GST_FLOW_EOS;
821     } else {
822       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
823           (_("This file is invalid and cannot be played.")),
824           ("atom has bogus size %" G_GUINT64_FORMAT, size));
825       return GST_FLOW_ERROR;
826     }
827   }
828
829   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
830
831   if (G_UNLIKELY (flow != GST_FLOW_OK))
832     return flow;
833
834   bsize = gst_buffer_get_size (*buf);
835   /* Catch short reads - we don't want any partial atoms */
836   if (G_UNLIKELY (bsize < size)) {
837     GST_WARNING_OBJECT (qtdemux,
838         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
839     gst_buffer_unref (*buf);
840     *buf = NULL;
841     return GST_FLOW_EOS;
842   }
843
844   return flow;
845 }
846
847 #if 1
848 static gboolean
849 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
850     GstFormat src_format, gint64 src_value, GstFormat dest_format,
851     gint64 * dest_value)
852 {
853   gboolean res = TRUE;
854   QtDemuxStream *stream = gst_pad_get_element_private (pad);
855   gint32 index;
856
857   if (stream->subtype != FOURCC_vide) {
858     res = FALSE;
859     goto done;
860   }
861
862   switch (src_format) {
863     case GST_FORMAT_TIME:
864       switch (dest_format) {
865         case GST_FORMAT_BYTES:{
866           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
867           if (-1 == index) {
868             res = FALSE;
869             goto done;
870           }
871
872           *dest_value = stream->samples[index].offset;
873
874           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
875               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
876               GST_TIME_ARGS (src_value), *dest_value);
877           break;
878         }
879         default:
880           res = FALSE;
881           break;
882       }
883       break;
884     case GST_FORMAT_BYTES:
885       switch (dest_format) {
886         case GST_FORMAT_TIME:{
887           index =
888               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
889               stream, src_value);
890
891           if (-1 == index) {
892             res = FALSE;
893             goto done;
894           }
895
896           *dest_value =
897               QTSTREAMTIME_TO_GSTTIME (stream,
898               stream->samples[index].timestamp);
899           GST_DEBUG_OBJECT (qtdemux,
900               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
901               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
902           break;
903         }
904         default:
905           res = FALSE;
906           break;
907       }
908       break;
909     default:
910       res = FALSE;
911       break;
912   }
913
914 done:
915   return res;
916 }
917 #endif
918
919 static gboolean
920 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
921 {
922   gboolean res = FALSE;
923
924   *duration = GST_CLOCK_TIME_NONE;
925
926   if (qtdemux->duration != 0 &&
927       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
928     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
929     res = TRUE;
930   } else {
931     *duration = GST_CLOCK_TIME_NONE;
932   }
933
934   return res;
935 }
936
937 static gboolean
938 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
939     GstQuery * query)
940 {
941   gboolean res = FALSE;
942   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
943
944   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
945
946   switch (GST_QUERY_TYPE (query)) {
947     case GST_QUERY_POSITION:{
948       GstFormat fmt;
949
950       gst_query_parse_position (query, &fmt, NULL);
951       if (fmt == GST_FORMAT_TIME
952           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
953         gst_query_set_position (query, GST_FORMAT_TIME,
954             qtdemux->segment.position);
955         res = TRUE;
956       }
957     }
958       break;
959     case GST_QUERY_DURATION:{
960       GstFormat fmt;
961
962       gst_query_parse_duration (query, &fmt, NULL);
963       if (fmt == GST_FORMAT_TIME) {
964         /* First try to query upstream */
965         res = gst_pad_query_default (pad, parent, query);
966         if (!res) {
967           GstClockTime duration;
968           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
969             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
970             res = TRUE;
971           }
972         }
973       }
974       break;
975     }
976     case GST_QUERY_CONVERT:{
977       GstFormat src_fmt, dest_fmt;
978       gint64 src_value, dest_value = 0;
979
980       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
981
982       res = gst_qtdemux_src_convert (qtdemux, pad,
983           src_fmt, src_value, dest_fmt, &dest_value);
984       if (res) {
985         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
986         res = TRUE;
987       }
988       break;
989     }
990     case GST_QUERY_FORMATS:
991       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
992       res = TRUE;
993       break;
994     case GST_QUERY_SEEKING:{
995       GstFormat fmt;
996       gboolean seekable;
997
998       /* try upstream first */
999       res = gst_pad_query_default (pad, parent, query);
1000
1001       if (!res) {
1002         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1003         if (fmt == GST_FORMAT_TIME) {
1004           GstClockTime duration;
1005
1006           gst_qtdemux_get_duration (qtdemux, &duration);
1007           seekable = TRUE;
1008           if (!qtdemux->pullbased) {
1009             GstQuery *q;
1010
1011             /* we might be able with help from upstream */
1012             seekable = FALSE;
1013             q = gst_query_new_seeking (GST_FORMAT_BYTES);
1014             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
1015               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
1016               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
1017             }
1018             gst_query_unref (q);
1019           }
1020           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
1021           res = TRUE;
1022         }
1023       }
1024       break;
1025     }
1026     case GST_QUERY_SEGMENT:
1027     {
1028       GstFormat format;
1029       gint64 start, stop;
1030
1031       format = qtdemux->segment.format;
1032
1033       start =
1034           gst_segment_to_stream_time (&qtdemux->segment, format,
1035           qtdemux->segment.start);
1036       if ((stop = qtdemux->segment.stop) == -1)
1037         stop = qtdemux->segment.duration;
1038       else
1039         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
1040
1041       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
1042       res = TRUE;
1043       break;
1044     }
1045     default:
1046       res = gst_pad_query_default (pad, parent, query);
1047       break;
1048   }
1049
1050   return res;
1051 }
1052
1053 static void
1054 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
1055 {
1056   if (G_LIKELY (stream->pad)) {
1057     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
1058         GST_DEBUG_PAD_NAME (stream->pad));
1059
1060     if (!gst_tag_list_is_empty (stream->stream_tags)) {
1061       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
1062           stream->stream_tags);
1063       gst_pad_push_event (stream->pad,
1064           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
1065 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
1066       /* post message qtdemux tag (for early recive application) */
1067       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
1068             gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
1069                   gst_tag_list_copy (stream->stream_tags)));
1070 #endif
1071     }
1072
1073     if (G_UNLIKELY (stream->send_global_tags)) {
1074       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
1075           qtdemux->tag_list);
1076       gst_pad_push_event (stream->pad,
1077           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
1078       stream->send_global_tags = FALSE;
1079     }
1080   }
1081 }
1082
1083 /* push event on all source pads; takes ownership of the event */
1084 static void
1085 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1086 {
1087   guint n;
1088   gboolean has_valid_stream = FALSE;
1089   GstEventType etype = GST_EVENT_TYPE (event);
1090
1091   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1092       GST_EVENT_TYPE_NAME (event));
1093
1094   for (n = 0; n < qtdemux->n_streams; n++) {
1095     GstPad *pad;
1096     QtDemuxStream *stream = qtdemux->streams[n];
1097     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1098
1099     if ((pad = stream->pad)) {
1100       has_valid_stream = TRUE;
1101
1102       if (etype == GST_EVENT_EOS) {
1103         /* let's not send twice */
1104         if (stream->sent_eos)
1105           continue;
1106         stream->sent_eos = TRUE;
1107       }
1108
1109       gst_pad_push_event (pad, gst_event_ref (event));
1110     }
1111   }
1112
1113   gst_event_unref (event);
1114
1115   /* if it is EOS and there are no pads, post an error */
1116   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1117     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1118   }
1119 }
1120
1121 /* push a pending newsegment event, if any from the streaming thread */
1122 static void
1123 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1124 {
1125   if (qtdemux->pending_newsegment) {
1126     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1127     qtdemux->pending_newsegment = NULL;
1128   }
1129 }
1130
1131 typedef struct
1132 {
1133   guint64 media_time;
1134 } FindData;
1135
1136 static gint
1137 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1138 {
1139   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1140     return 1;
1141   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1142     return 0;
1143
1144   return -1;
1145 }
1146
1147 /* find the index of the sample that includes the data for @media_time using a
1148  * binary search.  Only to be called in optimized cases of linear search below.
1149  *
1150  * Returns the index of the sample.
1151  */
1152 static guint32
1153 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1154     guint64 media_time)
1155 {
1156   QtDemuxSample *result;
1157   guint32 index;
1158
1159   /* convert media_time to mov format */
1160   media_time =
1161       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1162
1163   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1164       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1165       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1166
1167   if (G_LIKELY (result))
1168     index = result - str->samples;
1169   else
1170     index = 0;
1171
1172   return index;
1173 }
1174
1175
1176
1177 /* find the index of the sample that includes the data for @media_offset using a
1178  * linear search
1179  *
1180  * Returns the index of the sample.
1181  */
1182 static guint32
1183 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1184     QtDemuxStream * str, gint64 media_offset)
1185 {
1186   QtDemuxSample *result = str->samples;
1187   guint32 index = 0;
1188
1189   if (result == NULL || str->n_samples == 0)
1190     return -1;
1191
1192   if (media_offset == result->offset)
1193     return index;
1194
1195   result++;
1196   while (index < str->n_samples - 1) {
1197     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1198       goto parse_failed;
1199
1200     if (media_offset < result->offset)
1201       break;
1202
1203     index++;
1204     result++;
1205   }
1206   return index;
1207
1208   /* ERRORS */
1209 parse_failed:
1210   {
1211     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1212     return -1;
1213   }
1214 }
1215
1216 /* find the index of the sample that includes the data for @media_time using a
1217  * linear search, and keeping in mind that not all samples may have been parsed
1218  * yet.  If possible, it will delegate to binary search.
1219  *
1220  * Returns the index of the sample.
1221  */
1222 static guint32
1223 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1224     GstClockTime media_time)
1225 {
1226   guint32 index = 0;
1227   guint64 mov_time;
1228   QtDemuxSample *sample;
1229
1230   /* convert media_time to mov format */
1231   mov_time =
1232       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1233
1234   sample = str->samples;
1235   if (mov_time == sample->timestamp + sample->pts_offset)
1236     return index;
1237
1238   /* use faster search if requested time in already parsed range */
1239   sample = str->samples + str->stbl_index;
1240   if (str->stbl_index >= 0 &&
1241       mov_time <= (sample->timestamp + sample->pts_offset))
1242     return gst_qtdemux_find_index (qtdemux, str, media_time);
1243
1244   while (index < str->n_samples - 1) {
1245     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1246       goto parse_failed;
1247
1248     sample = str->samples + index + 1;
1249     if (mov_time < (sample->timestamp + sample->pts_offset))
1250       break;
1251
1252     index++;
1253   }
1254   return index;
1255
1256   /* ERRORS */
1257 parse_failed:
1258   {
1259     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1260     return -1;
1261   }
1262 }
1263
1264 /* find the index of the keyframe needed to decode the sample at @index
1265  * of stream @str, or of a subsequent keyframe (depending on @next)
1266  *
1267  * Returns the index of the keyframe.
1268  */
1269 static guint32
1270 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1271     guint32 index, gboolean next)
1272 {
1273   guint32 new_index = index;
1274
1275   if (index >= str->n_samples) {
1276     new_index = str->n_samples;
1277     goto beach;
1278   }
1279
1280   /* all keyframes, return index */
1281   if (str->all_keyframe) {
1282     new_index = index;
1283     goto beach;
1284   }
1285
1286   /* else search until we have a keyframe */
1287   while (new_index < str->n_samples) {
1288     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1289       goto parse_failed;
1290
1291     if (str->samples[new_index].keyframe)
1292       break;
1293
1294     if (new_index == 0)
1295       break;
1296
1297     if (next)
1298       new_index++;
1299     else
1300       new_index--;
1301   }
1302
1303   if (new_index == str->n_samples) {
1304     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1305     new_index = -1;
1306   }
1307
1308 beach:
1309   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1310       "gave %u", next ? "after" : "before", index, new_index);
1311
1312   return new_index;
1313
1314   /* ERRORS */
1315 parse_failed:
1316   {
1317     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1318     return -1;
1319   }
1320 }
1321
1322 /* find the segment for @time_position for @stream
1323  *
1324  * Returns the index of the segment containing @time_position.
1325  * Returns the last segment and sets the @eos variable to TRUE
1326  * if the time is beyond the end. @eos may be NULL
1327  */
1328 static guint32
1329 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1330     GstClockTime time_position)
1331 {
1332   gint i;
1333   guint32 seg_idx;
1334
1335   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1336       GST_TIME_ARGS (time_position));
1337
1338   seg_idx = -1;
1339   for (i = 0; i < stream->n_segments; i++) {
1340     QtDemuxSegment *segment = &stream->segments[i];
1341
1342     GST_LOG_OBJECT (stream->pad,
1343         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1344         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1345
1346     /* For the last segment we include stop_time in the last segment */
1347     if (i < stream->n_segments - 1) {
1348       if (segment->time <= time_position && time_position < segment->stop_time) {
1349         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1350         seg_idx = i;
1351         break;
1352       }
1353     } else {
1354       /* Last segment always matches */
1355       seg_idx = i;
1356       break;
1357     }
1358   }
1359   return seg_idx;
1360 }
1361
1362 /* move the stream @str to the sample position @index.
1363  *
1364  * Updates @str->sample_index and marks discontinuity if needed.
1365  */
1366 static void
1367 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1368     guint32 index)
1369 {
1370   /* no change needed */
1371   if (index == str->sample_index)
1372     return;
1373
1374   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1375       str->n_samples);
1376
1377   /* position changed, we have a discont */
1378   str->sample_index = index;
1379   str->offset_in_sample = 0;
1380   /* Each time we move in the stream we store the position where we are
1381    * starting from */
1382   str->from_sample = index;
1383   str->discont = TRUE;
1384 }
1385
1386 static void
1387 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1388     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1389 {
1390   guint64 min_offset;
1391   gint64 min_byte_offset = -1;
1392   gint n;
1393
1394   min_offset = desired_time;
1395
1396   /* for each stream, find the index of the sample in the segment
1397    * and move back to the previous keyframe. */
1398   for (n = 0; n < qtdemux->n_streams; n++) {
1399     QtDemuxStream *str;
1400     guint32 index, kindex;
1401     guint32 seg_idx;
1402     GstClockTime media_start;
1403     GstClockTime media_time;
1404     GstClockTime seg_time;
1405     QtDemuxSegment *seg;
1406     gboolean empty_segment = FALSE;
1407
1408     str = qtdemux->streams[n];
1409
1410     if (CUR_STREAM (str)->sparse && !use_sparse)
1411       continue;
1412
1413     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1414     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1415
1416     /* get segment and time in the segment */
1417     seg = &str->segments[seg_idx];
1418     seg_time = (desired_time - seg->time) * seg->rate;
1419
1420     while (QTSEGMENT_IS_EMPTY (seg)) {
1421       seg_time = 0;
1422       empty_segment = TRUE;
1423       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1424           seg_idx);
1425       seg_idx++;
1426       if (seg_idx == str->n_segments)
1427         break;
1428       seg = &str->segments[seg_idx];
1429     }
1430
1431     if (seg_idx == str->n_segments) {
1432       /* FIXME track shouldn't have the last segment as empty, but if it
1433        * happens we better handle it */
1434       continue;
1435     }
1436
1437     /* get the media time in the segment */
1438     media_start = seg->media_start + seg_time;
1439
1440     /* get the index of the sample with media time */
1441     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1442     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1443         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1444         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1445         empty_segment);
1446
1447     /* shift to next frame if we are looking for next keyframe */
1448     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1449         && index < str->stbl_index)
1450       index++;
1451
1452     if (!empty_segment) {
1453       /* find previous keyframe */
1454       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1455
1456       /* we will settle for one before if none found after */
1457       if (next && kindex == -1)
1458         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1459
1460       /* if the keyframe is at a different position, we need to update the
1461        * requested seek time */
1462       if (index != kindex) {
1463         index = kindex;
1464
1465         /* get timestamp of keyframe */
1466         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1467         GST_DEBUG_OBJECT (qtdemux,
1468             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1469             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1470             str->samples[kindex].offset);
1471
1472         /* keyframes in the segment get a chance to change the
1473          * desired_offset. keyframes out of the segment are
1474          * ignored. */
1475         if (media_time >= seg->media_start) {
1476           GstClockTime seg_time;
1477
1478           /* this keyframe is inside the segment, convert back to
1479            * segment time */
1480           seg_time = (media_time - seg->media_start) + seg->time;
1481           if ((!next && (seg_time < min_offset)) ||
1482               (next && (seg_time > min_offset)))
1483             min_offset = seg_time;
1484         }
1485       }
1486     }
1487
1488     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1489       min_byte_offset = str->samples[index].offset;
1490   }
1491
1492   if (key_time)
1493     *key_time = min_offset;
1494   if (key_offset)
1495     *key_offset = min_byte_offset;
1496 }
1497
1498 static gboolean
1499 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1500     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1501 {
1502   gboolean res;
1503
1504   g_return_val_if_fail (format != NULL, FALSE);
1505   g_return_val_if_fail (cur != NULL, FALSE);
1506   g_return_val_if_fail (stop != NULL, FALSE);
1507
1508   if (*format == GST_FORMAT_TIME)
1509     return TRUE;
1510
1511   res = TRUE;
1512   if (cur_type != GST_SEEK_TYPE_NONE)
1513     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1514   if (res && stop_type != GST_SEEK_TYPE_NONE)
1515     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1516
1517   if (res)
1518     *format = GST_FORMAT_TIME;
1519
1520   return res;
1521 }
1522
1523 /* perform seek in push based mode:
1524    find BYTE position to move to based on time and delegate to upstream
1525 */
1526 static gboolean
1527 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1528 {
1529   gdouble rate;
1530   GstFormat format;
1531   GstSeekFlags flags;
1532   GstSeekType cur_type, stop_type;
1533   gint64 cur, stop, key_cur;
1534   gboolean res;
1535   gint64 byte_cur;
1536   gint64 original_stop;
1537   guint32 seqnum;
1538
1539   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1540
1541   gst_event_parse_seek (event, &rate, &format, &flags,
1542       &cur_type, &cur, &stop_type, &stop);
1543   seqnum = gst_event_get_seqnum (event);
1544
1545   /* only forward streaming and seeking is possible */
1546   if (rate <= 0)
1547     goto unsupported_seek;
1548
1549   /* convert to TIME if needed and possible */
1550   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1551           stop_type, &stop))
1552     goto no_format;
1553
1554   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1555    * the original stop position to use when upstream pushes the new segment
1556    * for this seek */
1557   original_stop = stop;
1558   stop = -1;
1559
1560   /* find reasonable corresponding BYTE position,
1561    * also try to mind about keyframes, since we can not go back a bit for them
1562    * later on */
1563   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1564    * mostly just work, but let's not yet boldly go there  ... */
1565   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1566
1567   if (byte_cur == -1)
1568     goto abort_seek;
1569
1570   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1571       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1572       stop);
1573
1574   GST_OBJECT_LOCK (qtdemux);
1575   qtdemux->seek_offset = byte_cur;
1576   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1577     qtdemux->push_seek_start = cur;
1578   } else {
1579     qtdemux->push_seek_start = key_cur;
1580   }
1581
1582   if (stop_type == GST_SEEK_TYPE_NONE) {
1583     qtdemux->push_seek_stop = qtdemux->segment.stop;
1584   } else {
1585     qtdemux->push_seek_stop = original_stop;
1586   }
1587   GST_OBJECT_UNLOCK (qtdemux);
1588
1589   /* BYTE seek event */
1590   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1591       stop_type, stop);
1592   gst_event_set_seqnum (event, seqnum);
1593   res = gst_pad_push_event (qtdemux->sinkpad, event);
1594
1595   return res;
1596
1597   /* ERRORS */
1598 abort_seek:
1599   {
1600     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1601         "seek aborted.");
1602     return FALSE;
1603   }
1604 unsupported_seek:
1605   {
1606     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1607     return FALSE;
1608   }
1609 no_format:
1610   {
1611     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1612     return FALSE;
1613   }
1614 }
1615
1616 /* perform the seek.
1617  *
1618  * We set all segment_indexes in the streams to unknown and
1619  * adjust the time_position to the desired position. this is enough
1620  * to trigger a segment switch in the streaming thread to start
1621  * streaming from the desired position.
1622  *
1623  * Keyframe seeking is a little more complicated when dealing with
1624  * segments. Ideally we want to move to the previous keyframe in
1625  * the segment but there might not be a keyframe in the segment. In
1626  * fact, none of the segments could contain a keyframe. We take a
1627  * practical approach: seek to the previous keyframe in the segment,
1628  * if there is none, seek to the beginning of the segment.
1629  *
1630  * Called with STREAM_LOCK
1631  */
1632 static gboolean
1633 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1634     guint32 seqnum, GstSeekFlags flags)
1635 {
1636   gint64 desired_offset;
1637   gint n;
1638
1639   desired_offset = segment->position;
1640
1641   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1642       GST_TIME_ARGS (desired_offset));
1643
1644   /* may not have enough fragmented info to do this adjustment,
1645    * and we can't scan (and probably should not) at this time with
1646    * possibly flushing upstream */
1647   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1648     gint64 min_offset;
1649     gboolean next, before, after;
1650
1651     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1652     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1653     next = after && !before;
1654     if (segment->rate < 0)
1655       next = !next;
1656
1657     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1658         NULL);
1659     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1660         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1661     desired_offset = min_offset;
1662   }
1663
1664   /* and set all streams to the final position */
1665   gst_flow_combiner_reset (qtdemux->flowcombiner);
1666   qtdemux->segment_seqnum = seqnum;
1667   for (n = 0; n < qtdemux->n_streams; n++) {
1668     QtDemuxStream *stream = qtdemux->streams[n];
1669
1670     stream->time_position = desired_offset;
1671     stream->accumulated_base = 0;
1672     stream->sample_index = -1;
1673     stream->offset_in_sample = 0;
1674     stream->segment_index = -1;
1675     stream->sent_eos = FALSE;
1676
1677     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1678       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1679   }
1680   segment->position = desired_offset;
1681   segment->time = desired_offset;
1682   if (segment->rate >= 0) {
1683     segment->start = desired_offset;
1684
1685     /* we stop at the end */
1686     if (segment->stop == -1)
1687       segment->stop = segment->duration;
1688   } else {
1689     segment->stop = desired_offset;
1690   }
1691
1692   if (qtdemux->fragmented)
1693     qtdemux->fragmented_seek_pending = TRUE;
1694
1695   return TRUE;
1696 }
1697
1698 /* do a seek in pull based mode */
1699 static gboolean
1700 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1701 {
1702   gdouble rate;
1703   GstFormat format;
1704   GstSeekFlags flags;
1705   GstSeekType cur_type, stop_type;
1706   gint64 cur, stop;
1707   gboolean flush;
1708   gboolean update;
1709   GstSegment seeksegment;
1710   guint32 seqnum = 0;
1711   GstEvent *flush_event;
1712   gboolean ret;
1713
1714   if (event) {
1715     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1716
1717     gst_event_parse_seek (event, &rate, &format, &flags,
1718         &cur_type, &cur, &stop_type, &stop);
1719     seqnum = gst_event_get_seqnum (event);
1720
1721     /* we have to have a format as the segment format. Try to convert
1722      * if not. */
1723     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1724             stop_type, &stop))
1725       goto no_format;
1726
1727     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1728   } else {
1729     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1730     flags = 0;
1731   }
1732
1733   flush = flags & GST_SEEK_FLAG_FLUSH;
1734
1735   /* stop streaming, either by flushing or by pausing the task */
1736   if (flush) {
1737     flush_event = gst_event_new_flush_start ();
1738     if (seqnum)
1739       gst_event_set_seqnum (flush_event, seqnum);
1740     /* unlock upstream pull_range */
1741     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1742     /* make sure out loop function exits */
1743     gst_qtdemux_push_event (qtdemux, flush_event);
1744   } else {
1745     /* non flushing seek, pause the task */
1746     gst_pad_pause_task (qtdemux->sinkpad);
1747   }
1748
1749   /* wait for streaming to finish */
1750   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1751
1752   /* copy segment, we need this because we still need the old
1753    * segment when we close the current segment. */
1754   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1755
1756   if (event) {
1757     /* configure the segment with the seek variables */
1758     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1759     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1760             cur_type, cur, stop_type, stop, &update)) {
1761       ret = FALSE;
1762       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1763     } else {
1764       /* now do the seek */
1765       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1766     }
1767   } else {
1768     /* now do the seek */
1769     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1770   }
1771
1772   /* prepare for streaming again */
1773   if (flush) {
1774     flush_event = gst_event_new_flush_stop (TRUE);
1775     if (seqnum)
1776       gst_event_set_seqnum (flush_event, seqnum);
1777
1778     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1779     gst_qtdemux_push_event (qtdemux, flush_event);
1780   }
1781
1782   /* commit the new segment */
1783   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1784
1785   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1786     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1787         qtdemux->segment.format, qtdemux->segment.position);
1788     if (seqnum)
1789       gst_message_set_seqnum (msg, seqnum);
1790     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1791   }
1792
1793   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1794   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1795       qtdemux->sinkpad, NULL);
1796
1797   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1798
1799   return ret;
1800
1801   /* ERRORS */
1802 no_format:
1803   {
1804     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1805     return FALSE;
1806   }
1807 }
1808
1809 static gboolean
1810 qtdemux_ensure_index (GstQTDemux * qtdemux)
1811 {
1812   guint i;
1813
1814   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1815
1816   /* Build complete index */
1817   for (i = 0; i < qtdemux->n_streams; i++) {
1818     QtDemuxStream *stream = qtdemux->streams[i];
1819
1820     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1821       goto parse_error;
1822   }
1823   return TRUE;
1824
1825   /* ERRORS */
1826 parse_error:
1827   {
1828     GST_LOG_OBJECT (qtdemux,
1829         "Building complete index of stream %u for seeking failed!", i);
1830     return FALSE;
1831   }
1832 }
1833
1834 static gboolean
1835 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1836     GstEvent * event)
1837 {
1838   gboolean res = TRUE;
1839   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1840
1841   switch (GST_EVENT_TYPE (event)) {
1842     case GST_EVENT_SEEK:
1843     {
1844 #ifndef GST_DISABLE_GST_DEBUG
1845       GstClockTime ts = gst_util_get_timestamp ();
1846 #endif
1847       guint32 seqnum = gst_event_get_seqnum (event);
1848
1849       if (seqnum == qtdemux->segment_seqnum) {
1850         GST_LOG_OBJECT (pad,
1851             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1852         gst_event_unref (event);
1853         return TRUE;
1854       }
1855
1856       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1857         /* seek should be handled by upstream, we might need to re-download fragments */
1858         GST_DEBUG_OBJECT (qtdemux,
1859             "let upstream handle seek for fragmented playback");
1860         goto upstream;
1861       }
1862
1863       /* Build complete index for seeking;
1864        * if not a fragmented file at least */
1865       if (!qtdemux->fragmented)
1866         if (!qtdemux_ensure_index (qtdemux))
1867           goto index_failed;
1868 #ifndef GST_DISABLE_GST_DEBUG
1869       ts = gst_util_get_timestamp () - ts;
1870       GST_INFO_OBJECT (qtdemux,
1871           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1872 #endif
1873     }
1874       if (qtdemux->pullbased) {
1875         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1876       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1877         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1878         res = TRUE;
1879       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1880           && !qtdemux->fragmented) {
1881         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1882       } else {
1883         GST_DEBUG_OBJECT (qtdemux,
1884             "ignoring seek in push mode in current state");
1885         res = FALSE;
1886       }
1887       gst_event_unref (event);
1888       break;
1889     default:
1890     upstream:
1891       res = gst_pad_event_default (pad, parent, event);
1892       break;
1893   }
1894
1895 done:
1896   return res;
1897
1898   /* ERRORS */
1899 index_failed:
1900   {
1901     GST_ERROR_OBJECT (qtdemux, "Index failed");
1902     gst_event_unref (event);
1903     res = FALSE;
1904     goto done;
1905   }
1906 }
1907
1908 /* stream/index return sample that is min/max w.r.t. byte position,
1909  * time is min/max w.r.t. time of samples,
1910  * the latter need not be time of the former sample */
1911 static void
1912 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1913     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1914 {
1915   gint i, n, index;
1916   gint64 time, min_time;
1917   QtDemuxStream *stream;
1918
1919   min_time = -1;
1920   stream = NULL;
1921   index = -1;
1922
1923   for (n = 0; n < qtdemux->n_streams; ++n) {
1924     QtDemuxStream *str;
1925     gint inc;
1926     gboolean set_sample;
1927
1928     str = qtdemux->streams[n];
1929     set_sample = !set;
1930
1931     if (fw) {
1932       i = 0;
1933       inc = 1;
1934     } else {
1935       i = str->n_samples - 1;
1936       inc = -1;
1937     }
1938
1939     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1940       if (str->samples[i].size == 0)
1941         continue;
1942
1943       if (fw && (str->samples[i].offset < byte_pos))
1944         continue;
1945
1946       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1947         continue;
1948
1949       /* move stream to first available sample */
1950       if (set) {
1951         gst_qtdemux_move_stream (qtdemux, str, i);
1952         set_sample = TRUE;
1953       }
1954
1955       /* avoid index from sparse streams since they might be far away */
1956       if (!CUR_STREAM (str)->sparse) {
1957         /* determine min/max time */
1958         time = QTSAMPLE_PTS (str, &str->samples[i]);
1959         if (min_time == -1 || (!fw && time > min_time) ||
1960             (fw && time < min_time)) {
1961           min_time = time;
1962         }
1963
1964         /* determine stream with leading sample, to get its position */
1965         if (!stream ||
1966             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1967             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1968           stream = str;
1969           index = i;
1970         }
1971       }
1972       break;
1973     }
1974
1975     /* no sample for this stream, mark eos */
1976     if (!set_sample)
1977       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1978   }
1979
1980   if (_time)
1981     *_time = min_time;
1982   if (_stream)
1983     *_stream = stream;
1984   if (_index)
1985     *_index = index;
1986 }
1987
1988 static QtDemuxStream *
1989 _create_stream (void)
1990 {
1991   QtDemuxStream *stream;
1992
1993   stream = g_new0 (QtDemuxStream, 1);
1994   /* new streams always need a discont */
1995   stream->discont = TRUE;
1996   /* we enable clipping for raw audio/video streams */
1997   stream->need_clip = FALSE;
1998   stream->need_process = FALSE;
1999   stream->segment_index = -1;
2000   stream->time_position = 0;
2001   stream->sample_index = -1;
2002   stream->offset_in_sample = 0;
2003   stream->new_stream = TRUE;
2004   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
2005   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2006   stream->protected = FALSE;
2007   stream->protection_scheme_type = 0;
2008   stream->protection_scheme_version = 0;
2009   stream->protection_scheme_info = NULL;
2010   stream->n_samples_moof = 0;
2011   stream->duration_moof = 0;
2012   stream->duration_last_moof = 0;
2013   stream->alignment = 1;
2014   stream->stream_tags = gst_tag_list_new_empty ();
2015   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2016   g_queue_init (&stream->protection_scheme_event_queue);
2017   return stream;
2018 }
2019
2020 static gboolean
2021 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2022 {
2023   GstStructure *structure;
2024   const gchar *variant;
2025   const GstCaps *mediacaps = NULL;
2026
2027   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2028
2029   structure = gst_caps_get_structure (caps, 0);
2030   variant = gst_structure_get_string (structure, "variant");
2031
2032   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2033     QtDemuxStream *stream;
2034     const GValue *value;
2035
2036     demux->fragmented = TRUE;
2037     demux->mss_mode = TRUE;
2038
2039     if (demux->n_streams > 1) {
2040       /* can't do this, we can only renegotiate for another mss format */
2041       return FALSE;
2042     }
2043
2044     value = gst_structure_get_value (structure, "media-caps");
2045     /* create stream */
2046     if (value) {
2047       const GValue *timescale_v;
2048
2049       /* TODO update when stream changes during playback */
2050
2051       if (demux->n_streams == 0) {
2052         stream = _create_stream ();
2053         demux->streams[demux->n_streams] = stream;
2054         demux->n_streams = 1;
2055         /* mss has no stsd/stsd entry, use id 0 as default */
2056         stream->stsd_entries_length = 1;
2057         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2058         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2059       } else {
2060         stream = demux->streams[0];
2061       }
2062
2063       timescale_v = gst_structure_get_value (structure, "timescale");
2064       if (timescale_v) {
2065         stream->timescale = g_value_get_uint64 (timescale_v);
2066       } else {
2067         /* default mss timescale */
2068         stream->timescale = 10000000;
2069       }
2070       demux->timescale = stream->timescale;
2071
2072       mediacaps = gst_value_get_caps (value);
2073       if (!CUR_STREAM (stream)->caps
2074           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2075         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2076             mediacaps);
2077         stream->new_caps = TRUE;
2078       }
2079       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2080       structure = gst_caps_get_structure (mediacaps, 0);
2081       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2082         stream->subtype = FOURCC_vide;
2083
2084         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2085         gst_structure_get_int (structure, "height",
2086             &CUR_STREAM (stream)->height);
2087         gst_structure_get_fraction (structure, "framerate",
2088             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2089       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2090         gint rate = 0;
2091         stream->subtype = FOURCC_soun;
2092         gst_structure_get_int (structure, "channels",
2093             &CUR_STREAM (stream)->n_channels);
2094         gst_structure_get_int (structure, "rate", &rate);
2095         CUR_STREAM (stream)->rate = rate;
2096       }
2097     }
2098     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2099   } else {
2100     demux->mss_mode = FALSE;
2101   }
2102
2103   return TRUE;
2104 }
2105
2106 static void
2107 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2108 {
2109   gint n;
2110
2111   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2112   gst_pad_stop_task (qtdemux->sinkpad);
2113
2114   if (hard || qtdemux->upstream_format_is_time) {
2115     qtdemux->state = QTDEMUX_STATE_INITIAL;
2116     qtdemux->neededbytes = 16;
2117     qtdemux->todrop = 0;
2118     qtdemux->pullbased = FALSE;
2119     qtdemux->posted_redirect = FALSE;
2120     qtdemux->first_mdat = -1;
2121     qtdemux->header_size = 0;
2122     qtdemux->mdatoffset = -1;
2123     qtdemux->restoredata_offset = -1;
2124     if (qtdemux->mdatbuffer)
2125       gst_buffer_unref (qtdemux->mdatbuffer);
2126     if (qtdemux->restoredata_buffer)
2127       gst_buffer_unref (qtdemux->restoredata_buffer);
2128     qtdemux->mdatbuffer = NULL;
2129     qtdemux->restoredata_buffer = NULL;
2130     qtdemux->mdatleft = 0;
2131     qtdemux->mdatsize = 0;
2132     if (qtdemux->comp_brands)
2133       gst_buffer_unref (qtdemux->comp_brands);
2134     qtdemux->comp_brands = NULL;
2135     qtdemux->last_moov_offset = -1;
2136     if (qtdemux->moov_node_compressed) {
2137       g_node_destroy (qtdemux->moov_node_compressed);
2138       if (qtdemux->moov_node)
2139         g_free (qtdemux->moov_node->data);
2140     }
2141     qtdemux->moov_node_compressed = NULL;
2142     if (qtdemux->moov_node)
2143       g_node_destroy (qtdemux->moov_node);
2144     qtdemux->moov_node = NULL;
2145     if (qtdemux->tag_list)
2146       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2147     qtdemux->tag_list = gst_tag_list_new_empty ();
2148     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2149 #if 0
2150     if (qtdemux->element_index)
2151       gst_object_unref (qtdemux->element_index);
2152     qtdemux->element_index = NULL;
2153 #endif
2154     qtdemux->major_brand = 0;
2155     if (qtdemux->pending_newsegment)
2156       gst_event_unref (qtdemux->pending_newsegment);
2157     qtdemux->pending_newsegment = NULL;
2158     qtdemux->upstream_format_is_time = FALSE;
2159     qtdemux->upstream_seekable = FALSE;
2160     qtdemux->upstream_size = 0;
2161
2162     qtdemux->fragment_start = -1;
2163     qtdemux->fragment_start_offset = -1;
2164     qtdemux->duration = 0;
2165     qtdemux->moof_offset = 0;
2166     qtdemux->chapters_track_id = 0;
2167     qtdemux->have_group_id = FALSE;
2168     qtdemux->group_id = G_MAXUINT;
2169
2170     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2171         NULL);
2172     g_queue_clear (&qtdemux->protection_event_queue);
2173   }
2174   qtdemux->offset = 0;
2175   gst_adapter_clear (qtdemux->adapter);
2176   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2177   qtdemux->segment_seqnum = 0;
2178
2179   if (hard) {
2180     for (n = 0; n < qtdemux->n_streams; n++) {
2181       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2182       qtdemux->streams[n] = NULL;
2183     }
2184     qtdemux->n_streams = 0;
2185     qtdemux->n_video_streams = 0;
2186     qtdemux->n_audio_streams = 0;
2187     qtdemux->n_sub_streams = 0;
2188     qtdemux->exposed = FALSE;
2189     qtdemux->fragmented = FALSE;
2190     qtdemux->mss_mode = FALSE;
2191     gst_caps_replace (&qtdemux->media_caps, NULL);
2192     qtdemux->timescale = 0;
2193     qtdemux->got_moov = FALSE;
2194     if (qtdemux->protection_system_ids) {
2195       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2196       qtdemux->protection_system_ids = NULL;
2197     }
2198   } else if (qtdemux->mss_mode) {
2199     gst_flow_combiner_reset (qtdemux->flowcombiner);
2200     for (n = 0; n < qtdemux->n_streams; n++)
2201       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2202   } else {
2203     gst_flow_combiner_reset (qtdemux->flowcombiner);
2204     for (n = 0; n < qtdemux->n_streams; n++) {
2205       qtdemux->streams[n]->sent_eos = FALSE;
2206       qtdemux->streams[n]->time_position = 0;
2207       qtdemux->streams[n]->accumulated_base = 0;
2208     }
2209     if (!qtdemux->pending_newsegment) {
2210       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2211       if (qtdemux->segment_seqnum)
2212         gst_event_set_seqnum (qtdemux->pending_newsegment,
2213             qtdemux->segment_seqnum);
2214     }
2215   }
2216 }
2217
2218
2219 /* Maps the @segment to the qt edts internal segments and pushes
2220  * the correspnding segment event.
2221  *
2222  * If it ends up being at a empty segment, a gap will be pushed and the next
2223  * edts segment will be activated in sequence.
2224  *
2225  * To be used in push-mode only */
2226 static void
2227 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2228 {
2229   gint n, i;
2230
2231   for (n = 0; n < qtdemux->n_streams; n++) {
2232     QtDemuxStream *stream = qtdemux->streams[n];
2233
2234     stream->time_position = segment->start;
2235
2236     /* in push mode we should be guaranteed that we will have empty segments
2237      * at the beginning and then one segment after, other scenarios are not
2238      * supported and are discarded when parsing the edts */
2239     for (i = 0; i < stream->n_segments; i++) {
2240       if (stream->segments[i].stop_time > segment->start) {
2241         gst_qtdemux_activate_segment (qtdemux, stream, i,
2242             stream->time_position);
2243         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2244           /* push the empty segment and move to the next one */
2245           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2246               stream->time_position);
2247           continue;
2248         }
2249
2250         g_assert (i == stream->n_segments - 1);
2251       }
2252     }
2253   }
2254 }
2255
2256 static gboolean
2257 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2258     GstEvent * event)
2259 {
2260   GstQTDemux *demux = GST_QTDEMUX (parent);
2261   gboolean res = TRUE;
2262
2263   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2264
2265   switch (GST_EVENT_TYPE (event)) {
2266     case GST_EVENT_SEGMENT:
2267     {
2268       gint64 offset = 0;
2269       QtDemuxStream *stream;
2270       gint idx;
2271       GstSegment segment;
2272
2273       /* some debug output */
2274       gst_event_copy_segment (event, &segment);
2275       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2276           &segment);
2277
2278       /* erase any previously set segment */
2279       gst_event_replace (&demux->pending_newsegment, NULL);
2280
2281       if (segment.format == GST_FORMAT_TIME) {
2282         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2283         gst_event_replace (&demux->pending_newsegment, event);
2284         demux->upstream_format_is_time = TRUE;
2285       } else {
2286         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2287             "not in time format");
2288
2289         /* chain will send initial newsegment after pads have been added */
2290         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2291           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2292           goto exit;
2293         }
2294       }
2295
2296       /* check if this matches a time seek we received previously
2297        * FIXME for backwards compatibility reasons we use the
2298        * seek_offset here to compare. In the future we might want to
2299        * change this to use the seqnum as it uniquely should identify
2300        * the segment that corresponds to the seek. */
2301       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2302           ", received segment offset %" G_GINT64_FORMAT,
2303           demux->seek_offset, segment.start);
2304       if (segment.format == GST_FORMAT_BYTES
2305           && demux->seek_offset == segment.start) {
2306         GST_OBJECT_LOCK (demux);
2307         offset = segment.start;
2308
2309         segment.format = GST_FORMAT_TIME;
2310         segment.start = demux->push_seek_start;
2311         segment.stop = demux->push_seek_stop;
2312         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2313             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2314             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2315         GST_OBJECT_UNLOCK (demux);
2316       }
2317
2318       /* we only expect a BYTE segment, e.g. following a seek */
2319       if (segment.format == GST_FORMAT_BYTES) {
2320         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2321           offset = segment.start;
2322
2323           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2324               NULL, (gint64 *) & segment.start);
2325           if ((gint64) segment.start < 0)
2326             segment.start = 0;
2327         }
2328         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2329           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2330               NULL, (gint64 *) & segment.stop);
2331           /* keyframe seeking should already arrange for start >= stop,
2332            * but make sure in other rare cases */
2333           segment.stop = MAX (segment.stop, segment.start);
2334         }
2335       } else if (segment.format == GST_FORMAT_TIME) {
2336         /* push all data on the adapter before starting this
2337          * new segment */
2338         gst_qtdemux_process_adapter (demux, TRUE);
2339       } else {
2340         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2341         goto exit;
2342       }
2343
2344       /* We shouldn't modify upstream driven TIME FORMAT segment */
2345       if (!demux->upstream_format_is_time) {
2346         /* accept upstream's notion of segment and distribute along */
2347         segment.format = GST_FORMAT_TIME;
2348         segment.position = segment.time = segment.start;
2349         segment.duration = demux->segment.duration;
2350         segment.base = gst_segment_to_running_time (&demux->segment,
2351             GST_FORMAT_TIME, demux->segment.position);
2352       }
2353
2354       gst_segment_copy_into (&segment, &demux->segment);
2355       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2356
2357       /* map segment to internal qt segments and push on each stream */
2358       if (demux->n_streams) {
2359         if (demux->fragmented) {
2360           GstEvent *segment_event = gst_event_new_segment (&segment);
2361
2362           gst_event_replace (&demux->pending_newsegment, NULL);
2363           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2364           gst_qtdemux_push_event (demux, segment_event);
2365         } else {
2366           gst_event_replace (&demux->pending_newsegment, NULL);
2367           gst_qtdemux_map_and_push_segments (demux, &segment);
2368         }
2369       }
2370
2371       /* clear leftover in current segment, if any */
2372       gst_adapter_clear (demux->adapter);
2373
2374       /* set up streaming thread */
2375       demux->offset = offset;
2376       if (demux->upstream_format_is_time) {
2377         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2378             "set values to restart reading from a new atom");
2379         demux->neededbytes = 16;
2380         demux->todrop = 0;
2381       } else {
2382         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2383             NULL);
2384         if (stream) {
2385           demux->todrop = stream->samples[idx].offset - offset;
2386           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2387         } else {
2388           /* set up for EOS */
2389           demux->neededbytes = -1;
2390           demux->todrop = 0;
2391         }
2392       }
2393     exit:
2394       gst_event_unref (event);
2395       res = TRUE;
2396       goto drop;
2397     }
2398     case GST_EVENT_FLUSH_START:
2399     {
2400       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2401         gst_event_unref (event);
2402         goto drop;
2403       }
2404       break;
2405     }
2406     case GST_EVENT_FLUSH_STOP:
2407     {
2408       guint64 dur;
2409
2410       dur = demux->segment.duration;
2411       gst_qtdemux_reset (demux, FALSE);
2412       demux->segment.duration = dur;
2413
2414       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2415         gst_event_unref (event);
2416         goto drop;
2417       }
2418       break;
2419     }
2420     case GST_EVENT_EOS:
2421       /* If we are in push mode, and get an EOS before we've seen any streams,
2422        * then error out - we have nowhere to send the EOS */
2423       if (!demux->pullbased) {
2424         gint i;
2425         gboolean has_valid_stream = FALSE;
2426         for (i = 0; i < demux->n_streams; i++) {
2427           if (demux->streams[i]->pad != NULL) {
2428             has_valid_stream = TRUE;
2429             break;
2430           }
2431         }
2432         if (!has_valid_stream)
2433           gst_qtdemux_post_no_playable_stream_error (demux);
2434         else {
2435           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2436               (guint) gst_adapter_available (demux->adapter));
2437           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2438             res = FALSE;
2439           }
2440         }
2441       }
2442       break;
2443     case GST_EVENT_CAPS:{
2444       GstCaps *caps = NULL;
2445
2446       gst_event_parse_caps (event, &caps);
2447       gst_qtdemux_setcaps (demux, caps);
2448       res = TRUE;
2449       gst_event_unref (event);
2450       goto drop;
2451     }
2452     case GST_EVENT_PROTECTION:
2453     {
2454       const gchar *system_id = NULL;
2455
2456       gst_event_parse_protection (event, &system_id, NULL, NULL);
2457       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2458           system_id);
2459       gst_qtdemux_append_protection_system_id (demux, system_id);
2460       /* save the event for later, for source pads that have not been created */
2461       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2462       /* send it to all pads that already exist */
2463       gst_qtdemux_push_event (demux, event);
2464       res = TRUE;
2465       goto drop;
2466     }
2467     default:
2468       break;
2469   }
2470
2471   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2472
2473 drop:
2474   return res;
2475 }
2476
2477 #if 0
2478 static void
2479 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2480 {
2481   GstQTDemux *demux = GST_QTDEMUX (element);
2482
2483   GST_OBJECT_LOCK (demux);
2484   if (demux->element_index)
2485     gst_object_unref (demux->element_index);
2486   if (index) {
2487     demux->element_index = gst_object_ref (index);
2488   } else {
2489     demux->element_index = NULL;
2490   }
2491   GST_OBJECT_UNLOCK (demux);
2492   /* object lock might be taken again */
2493   if (index)
2494     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2495   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2496       demux->element_index, demux->index_id);
2497 }
2498
2499 static GstIndex *
2500 gst_qtdemux_get_index (GstElement * element)
2501 {
2502   GstIndex *result = NULL;
2503   GstQTDemux *demux = GST_QTDEMUX (element);
2504
2505   GST_OBJECT_LOCK (demux);
2506   if (demux->element_index)
2507     result = gst_object_ref (demux->element_index);
2508   GST_OBJECT_UNLOCK (demux);
2509
2510   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2511
2512   return result;
2513 }
2514 #endif
2515
2516 static void
2517 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2518 {
2519   g_free ((gpointer) stream->stco.data);
2520   stream->stco.data = NULL;
2521   g_free ((gpointer) stream->stsz.data);
2522   stream->stsz.data = NULL;
2523   g_free ((gpointer) stream->stsc.data);
2524   stream->stsc.data = NULL;
2525   g_free ((gpointer) stream->stts.data);
2526   stream->stts.data = NULL;
2527   g_free ((gpointer) stream->stss.data);
2528   stream->stss.data = NULL;
2529   g_free ((gpointer) stream->stps.data);
2530   stream->stps.data = NULL;
2531   g_free ((gpointer) stream->ctts.data);
2532   stream->ctts.data = NULL;
2533 }
2534
2535 static void
2536 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2537     QtDemuxStream * stream)
2538 {
2539   g_free (stream->segments);
2540   stream->segments = NULL;
2541   stream->segment_index = -1;
2542   stream->accumulated_base = 0;
2543 }
2544
2545 static void
2546 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2547     QtDemuxStream * stream)
2548 {
2549   g_free (stream->samples);
2550   stream->samples = NULL;
2551   gst_qtdemux_stbl_free (stream);
2552
2553   /* fragments */
2554   g_free (stream->ra_entries);
2555   stream->ra_entries = NULL;
2556   stream->n_ra_entries = 0;
2557
2558   stream->sample_index = -1;
2559   stream->stbl_index = -1;
2560   stream->n_samples = 0;
2561   stream->time_position = 0;
2562
2563   stream->n_samples_moof = 0;
2564   stream->duration_moof = 0;
2565   stream->duration_last_moof = 0;
2566 }
2567
2568 static void
2569 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2570 {
2571   gint i;
2572   if (stream->allocator)
2573     gst_object_unref (stream->allocator);
2574   while (stream->buffers) {
2575     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2576     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2577   }
2578   for (i = 0; i < stream->stsd_entries_length; i++) {
2579     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2580     if (entry->rgb8_palette) {
2581       gst_memory_unref (entry->rgb8_palette);
2582       entry->rgb8_palette = NULL;
2583     }
2584     entry->sparse = FALSE;
2585   }
2586
2587   gst_tag_list_unref (stream->stream_tags);
2588   stream->stream_tags = gst_tag_list_new_empty ();
2589   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2590   g_free (stream->redirect_uri);
2591   stream->redirect_uri = NULL;
2592   stream->sent_eos = FALSE;
2593   stream->protected = FALSE;
2594   if (stream->protection_scheme_info) {
2595     if (stream->protection_scheme_type == FOURCC_cenc) {
2596       QtDemuxCencSampleSetInfo *info =
2597           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2598       if (info->default_properties)
2599         gst_structure_free (info->default_properties);
2600       if (info->crypto_info)
2601         g_ptr_array_free (info->crypto_info, TRUE);
2602     }
2603     g_free (stream->protection_scheme_info);
2604     stream->protection_scheme_info = NULL;
2605   }
2606   stream->protection_scheme_type = 0;
2607   stream->protection_scheme_version = 0;
2608   g_queue_foreach (&stream->protection_scheme_event_queue,
2609       (GFunc) gst_event_unref, NULL);
2610   g_queue_clear (&stream->protection_scheme_event_queue);
2611   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2612   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2613 }
2614
2615 static void
2616 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2617 {
2618   gint i;
2619   gst_qtdemux_stream_clear (qtdemux, stream);
2620   for (i = 0; i < stream->stsd_entries_length; i++) {
2621     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2622     if (entry->caps) {
2623       gst_caps_unref (entry->caps);
2624       entry->caps = NULL;
2625     }
2626   }
2627   gst_tag_list_unref (stream->stream_tags);
2628   if (stream->pad) {
2629     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2630     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2631   }
2632   g_free (stream->stsd_entries);
2633   g_free (stream);
2634 }
2635
2636 static void
2637 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2638 {
2639   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2640
2641   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2642   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2643   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2644   qtdemux->n_streams--;
2645 }
2646
2647 static GstStateChangeReturn
2648 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2649 {
2650   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2651   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2652
2653   switch (transition) {
2654     case GST_STATE_CHANGE_PAUSED_TO_READY:
2655       break;
2656     default:
2657       break;
2658   }
2659
2660   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2661
2662   switch (transition) {
2663     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2664       gst_qtdemux_reset (qtdemux, TRUE);
2665       break;
2666     }
2667     default:
2668       break;
2669   }
2670
2671   return result;
2672 }
2673
2674 static void
2675 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2676 {
2677   /* counts as header data */
2678   qtdemux->header_size += length;
2679
2680   /* only consider at least a sufficiently complete ftyp atom */
2681   if (length >= 20) {
2682     GstBuffer *buf;
2683
2684     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2685     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2686         GST_FOURCC_ARGS (qtdemux->major_brand));
2687     if (qtdemux->comp_brands)
2688       gst_buffer_unref (qtdemux->comp_brands);
2689     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2690     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2691   }
2692 }
2693
2694 static void
2695 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2696     GstTagList * xmptaglist)
2697 {
2698   /* Strip out bogus fields */
2699   if (xmptaglist) {
2700     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2701       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2702       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2703     } else {
2704       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2705     }
2706
2707     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2708
2709     /* prioritize native tags using _KEEP mode */
2710     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2711     gst_tag_list_unref (xmptaglist);
2712   }
2713 }
2714
2715 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
2716 static void
2717 _get_int_value_from_xml_string (GstQTDemux * qtdemux,
2718     const char *xml_str, const char *param_name, int *value)
2719 {
2720   char *value_start, *value_end, *endptr;
2721   const short value_length_max = 12;
2722   char init_view_ret[12];
2723   int value_length = 0;
2724   int i = 0;
2725
2726   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2727
2728   if (!value_start) {
2729     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2730         param_name);
2731     return;
2732   }
2733
2734   value_start += strlen (param_name);
2735   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2736     value_start++;
2737
2738   value_end = strchr (value_start, '<');
2739   if (!value_end) {
2740     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2741     return;
2742   }
2743
2744   value_length = value_end - value_start;
2745   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2746           || (value_start[value_length - 1] == '\t')))
2747     value_length--;
2748
2749   if (value_start[i] == '+' || value_start[i] == '-')
2750     i++;
2751   while (i < value_length) {
2752     if (value_start[i] < '0' || value_start[i] > '9') {
2753       GST_ERROR_OBJECT (qtdemux,
2754           "error: incorrect value, integer was expected\n");
2755       return;
2756     }
2757     i++;
2758   }
2759
2760   if (value_length >= value_length_max || value_length < 1) {
2761     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2762     return;
2763   }
2764
2765   strncpy (init_view_ret, value_start, value_length_max);
2766   init_view_ret[value_length] = '\0';
2767
2768   *value = strtol (init_view_ret, &endptr, 10);
2769   if (endptr == init_view_ret) {
2770     GST_ERROR_OBJECT (qtdemux, "error: no digits were found\n");
2771     return;
2772   }
2773
2774   return;
2775 }
2776
2777 static void
2778 _get_string_value_from_xml_string (GstQTDemux * qtdemux,
2779     const char *xml_str, const char *param_name, char **value)
2780 {
2781   char *value_start, *value_end;
2782   const short value_length_max = 256;
2783   int value_length = 0;
2784
2785   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2786
2787   if (!value_start) {
2788     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2789         param_name);
2790     return;
2791   }
2792
2793   value_start += strlen (param_name);
2794   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2795     value_start++;
2796
2797   value_end = strchr (value_start, '<');
2798   if (!value_end) {
2799     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2800     return;
2801   }
2802
2803   value_length = value_end - value_start;
2804   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2805           || (value_start[value_length - 1] == '\t')))
2806     value_length--;
2807
2808   if (value_length >= value_length_max || value_length < 1) {
2809     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2810     return;
2811   }
2812
2813   *value = (char *) malloc (value_length);
2814
2815   if (*value == NULL) {
2816     GST_ERROR_OBJECT (qtdemux, "error: malloc failed\n");
2817     return;
2818   }
2819
2820   strncpy (*value, value_start, value_length);
2821
2822   return;
2823 }
2824
2825 static void
2826 _get_bool_value_from_xml_string (GstQTDemux * qtdemux,
2827     const char *xml_str, const char *param_name, gboolean * value)
2828 {
2829   char *value_start, *value_end;
2830   int value_length = 0;
2831
2832   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
2833
2834   if (!value_start) {
2835     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
2836         param_name);
2837     return;
2838   }
2839
2840   value_start += strlen (param_name);
2841   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
2842     value_start++;
2843
2844   value_end = strchr (value_start, '<');
2845   if (!value_end) {
2846     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
2847     return;
2848   }
2849
2850   value_length = value_end - value_start;
2851   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
2852           || (value_start[value_length - 1] == '\t')))
2853     value_length--;
2854
2855   if (value_length < 1) {
2856     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
2857     return;
2858   }
2859
2860   *value = strstr (value_start, "true") ? TRUE : FALSE;
2861
2862   return;
2863 }
2864
2865 static void
2866 _parse_spatial_video_metadata_from_xml_string (GstQTDemux * qtdemux,
2867     const char *xmlStr, QtDemuxSphericalMetadata * spherical_metadata)
2868 {
2869   const char is_spherical_str[] = "<GSpherical:Spherical>";
2870   const char is_stitched_str[] = "<GSpherical:Stitched>";
2871   const char stitching_software_str[] = "<GSpherical:StitchingSoftware>";
2872   const char projection_type_str[] = "<GSpherical:ProjectionType>";
2873   const char stereo_mode_str[] = "<GSpherical:StereoMode>";
2874   const char source_count_str[] = "<GSpherical:SourceCount>";
2875   const char init_view_heading_str[] = "<GSpherical:InitialViewHeadingDegrees>";
2876   const char init_view_pitch_str[] = "<GSpherical:InitialViewPitchDegrees>";
2877   const char init_view_roll_str[] = "<GSpherical:InitialViewRollDegrees>";
2878   const char timestamp_str[] = "<GSpherical:Timestamp>";
2879   const char full_pano_width_str[] = "<GSpherical:FullPanoWidthPixels>";
2880   const char full_pano_height_str[] = "<GSpherical:FullPanoHeightPixels>";
2881   const char cropped_area_image_width_str[] =
2882       "<GSpherical:CroppedAreaImageWidthPixels>";
2883   const char cropped_area_image_height_str[] =
2884       "<GSpherical:CroppedAreaImageHeightPixels>";
2885   const char cropped_area_left_str[] = "<GSpherical:CroppedAreaLeftPixels>";
2886   const char cropped_area_top_str[] = "<GSpherical:CroppedAreaTopPixels>";
2887
2888   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_spherical_str,
2889       (gboolean *) & spherical_metadata->is_spherical);
2890   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_stitched_str,
2891       (gboolean *) & spherical_metadata->is_stitched);
2892
2893   if (spherical_metadata->is_spherical && spherical_metadata->is_stitched) {
2894     _get_string_value_from_xml_string (qtdemux, xmlStr,
2895         stitching_software_str, &spherical_metadata->stitching_software);
2896     _get_string_value_from_xml_string (qtdemux, xmlStr,
2897         projection_type_str, &spherical_metadata->projection_type);
2898     _get_string_value_from_xml_string (qtdemux, xmlStr, stereo_mode_str,
2899         &spherical_metadata->stereo_mode);
2900     _get_int_value_from_xml_string (qtdemux, xmlStr, source_count_str,
2901         &spherical_metadata->source_count);
2902     _get_int_value_from_xml_string (qtdemux, xmlStr,
2903         init_view_heading_str, &spherical_metadata->init_view_heading);
2904     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_pitch_str,
2905         &spherical_metadata->init_view_pitch);
2906     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_roll_str,
2907         &spherical_metadata->init_view_roll);
2908     _get_int_value_from_xml_string (qtdemux, xmlStr, timestamp_str,
2909         &spherical_metadata->timestamp);
2910     _get_int_value_from_xml_string (qtdemux, xmlStr, full_pano_width_str,
2911         &spherical_metadata->full_pano_width_pixels);
2912     _get_int_value_from_xml_string (qtdemux, xmlStr,
2913         full_pano_height_str, &spherical_metadata->full_pano_height_pixels);
2914     _get_int_value_from_xml_string (qtdemux, xmlStr,
2915         cropped_area_image_width_str,
2916         &spherical_metadata->cropped_area_image_width);
2917     _get_int_value_from_xml_string (qtdemux, xmlStr,
2918         cropped_area_image_height_str,
2919         &spherical_metadata->cropped_area_image_height);
2920     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_left_str,
2921         &spherical_metadata->cropped_area_left);
2922     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_top_str,
2923         &spherical_metadata->cropped_area_top);
2924   }
2925
2926   return;
2927 }
2928
2929 static void
2930 gst_tag_register_spherical_tags (void) {
2931   gst_tag_register ("is_spherical", GST_TAG_FLAG_META,
2932       G_TYPE_INT,
2933       _("tag-spherical"),
2934       _("Flag indicating if the video is a spherical video"),
2935       NULL);
2936   gst_tag_register ("is_stitched", GST_TAG_FLAG_META,
2937       G_TYPE_INT,
2938       _("tag-stitched"),
2939       _("Flag indicating if the video is stitched"),
2940       NULL);
2941   gst_tag_register ("stitching_software", GST_TAG_FLAG_META,
2942       G_TYPE_STRING,
2943       _("tag-stitching-software"),
2944       _("Software used to stitch the spherical video"),
2945       NULL);
2946   gst_tag_register ("projection_type", GST_TAG_FLAG_META,
2947       G_TYPE_STRING,
2948       _("tag-projection-type"),
2949       _("Projection type used in the video frames"),
2950       NULL);
2951   gst_tag_register ("stereo_mode", GST_TAG_FLAG_META,
2952       G_TYPE_STRING,
2953       _("tag-stereo-mode"),
2954       _("Description of stereoscopic 3D layout"),
2955       NULL);
2956   gst_tag_register ("source_count", GST_TAG_FLAG_META,
2957       G_TYPE_INT,
2958       _("tag-source-count"),
2959       _("Number of cameras used to create the spherical video"),
2960       NULL);
2961   gst_tag_register ("init_view_heading", GST_TAG_FLAG_META,
2962       G_TYPE_INT,
2963       _("tag-init-view-heading"),
2964       _("The heading angle of the initial view in degrees"),
2965       NULL);
2966   gst_tag_register ("init_view_pitch", GST_TAG_FLAG_META,
2967       G_TYPE_INT,
2968       _("tag-init-view-pitch"),
2969       _("The pitch angle of the initial view in degrees"),
2970       NULL);
2971   gst_tag_register ("init_view_roll", GST_TAG_FLAG_META,
2972       G_TYPE_INT,
2973       _("tag-init-view-roll"),
2974       _("The roll angle of the initial view in degrees"),
2975       NULL);
2976   gst_tag_register ("timestamp", GST_TAG_FLAG_META,
2977       G_TYPE_INT,
2978       _("tag-timestamp"),
2979       _("Epoch timestamp of when the first frame in the video was recorded"),
2980       NULL);
2981   gst_tag_register ("full_pano_width_pixels", GST_TAG_FLAG_META,
2982       G_TYPE_INT,
2983       _("tag-full-pano-width"),
2984       _("Width of the encoded video frame in pixels"),
2985       NULL);
2986   gst_tag_register ("full_pano_height_pixels", GST_TAG_FLAG_META,
2987       G_TYPE_INT,
2988       _("tag-full-pano-height"),
2989       _("Height of the encoded video frame in pixels"),
2990       NULL);
2991   gst_tag_register ("cropped_area_image_width", GST_TAG_FLAG_META,
2992       G_TYPE_INT,
2993       _("tag-cropped-area-image-width"),
2994       _("Width of the video frame to display (e.g. cropping)"),
2995       NULL);
2996   gst_tag_register ("cropped_area_image_height", GST_TAG_FLAG_META,
2997       G_TYPE_INT,
2998       _("tag-cropped-area-image-height"),
2999       _("Height of the video frame to display (e.g. cropping)"),
3000       NULL);
3001   gst_tag_register ("cropped_area_left", GST_TAG_FLAG_META,
3002       G_TYPE_INT,
3003       _("tag-cropped-area-left"),
3004       _("Column where the left edge of the image was cropped from the"
3005           " full sized panorama"),
3006       NULL);
3007   gst_tag_register ("cropped_area_top", GST_TAG_FLAG_META,
3008       G_TYPE_INT,
3009       _("tag-cropped-area-top"),
3010       _("Row where the top edge of the image was cropped from the"
3011           " full sized panorama"),
3012       NULL);
3013   gst_tag_register ("ambisonic_type", GST_TAG_FLAG_META,
3014       G_TYPE_INT,
3015       _("tag-ambisonic-type"),
3016       _("Specifies the type of ambisonic audio represented"),
3017       NULL);
3018   gst_tag_register ("ambisonic_format", GST_TAG_FLAG_META,
3019       G_TYPE_INT,
3020       _("tag-ambisonic-format"),
3021       _("Specifies the ambisonic audio format"),
3022       NULL);
3023   gst_tag_register ("ambisonic_order", GST_TAG_FLAG_META,
3024       G_TYPE_INT,
3025       _("tag-ambisonic-order"),
3026       _("Specifies the ambisonic audio channel order"),
3027       NULL);
3028
3029   return;
3030 }
3031
3032 static void
3033 _send_message_to_bus (GstQTDemux * qtdemux,
3034     QtDemuxSphericalMetadata * spherical_metadata)
3035 {
3036   GstTagList *taglist;
3037
3038   GST_DEBUG_OBJECT (qtdemux, "is_spherical = %d",
3039       spherical_metadata->is_spherical);
3040   GST_DEBUG_OBJECT (qtdemux, "is_stitched = %d",
3041       spherical_metadata->is_stitched);
3042   GST_DEBUG_OBJECT (qtdemux, "stitching_software = %s",
3043       spherical_metadata->stitching_software);
3044   GST_DEBUG_OBJECT (qtdemux, "projection_type = %s",
3045       spherical_metadata->projection_type);
3046   GST_DEBUG_OBJECT (qtdemux, "stereo_mode = %s",
3047       spherical_metadata->stereo_mode);
3048   GST_DEBUG_OBJECT (qtdemux, "source_count %d",
3049       spherical_metadata->source_count);
3050   GST_DEBUG_OBJECT (qtdemux, "init_view_heading = %d",
3051       spherical_metadata->init_view_heading);
3052   GST_DEBUG_OBJECT (qtdemux, "init_view_pitch = %d",
3053       spherical_metadata->init_view_pitch);
3054   GST_DEBUG_OBJECT (qtdemux, "init_view_roll = %d",
3055       spherical_metadata->init_view_roll);
3056   GST_DEBUG_OBJECT (qtdemux, "timestamp = %d", spherical_metadata->timestamp);
3057   GST_DEBUG_OBJECT (qtdemux, "full_pano_width_pixels = %d",
3058       spherical_metadata->full_pano_width_pixels);
3059   GST_DEBUG_OBJECT (qtdemux, "full_pano_height_pixels = %d",
3060       spherical_metadata->full_pano_height_pixels);
3061   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_width = %d",
3062       spherical_metadata->cropped_area_image_width);
3063   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_height = %d",
3064       spherical_metadata->cropped_area_image_height);
3065   GST_DEBUG_OBJECT (qtdemux, "cropped_area_left = %d",
3066       spherical_metadata->cropped_area_left);
3067   GST_DEBUG_OBJECT (qtdemux, "cropped_area_top = %d",
3068       spherical_metadata->cropped_area_top);
3069   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type = %d",
3070       spherical_metadata->ambisonic_type);
3071   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order = %d",
3072       spherical_metadata->ambisonic_order);
3073   GST_DEBUG_OBJECT (qtdemux, "ambisonic_format = %d",
3074       spherical_metadata->ambisonic_format);
3075
3076   taglist = gst_tag_list_new_empty ();
3077   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3078       "is_spherical", spherical_metadata->is_spherical,
3079       "is_stitched", spherical_metadata->is_stitched,
3080       "source_count", spherical_metadata->source_count,
3081       "init_view_heading", spherical_metadata->init_view_heading,
3082       "init_view_pitch", spherical_metadata->init_view_pitch,
3083       "init_view_roll", spherical_metadata->init_view_roll,
3084       "timestamp", spherical_metadata->timestamp,
3085       "full_pano_width_pixels", spherical_metadata->full_pano_width_pixels,
3086       "full_pano_height_pixels", spherical_metadata->full_pano_height_pixels,
3087       "cropped_area_image_width", spherical_metadata->cropped_area_image_width,
3088       "cropped_area_image_height", spherical_metadata->cropped_area_image_height,
3089       "cropped_area_left", spherical_metadata->cropped_area_left,
3090       "cropped_area_top", spherical_metadata->cropped_area_top,
3091       "ambisonic_type", spherical_metadata->ambisonic_type,
3092       "ambisonic_format", spherical_metadata->ambisonic_format,
3093       "ambisonic_order", spherical_metadata->ambisonic_order,
3094       NULL);
3095
3096   if (spherical_metadata->stitching_software)
3097     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3098         "stitching_software", spherical_metadata->stitching_software,
3099         NULL);
3100   if (spherical_metadata->projection_type)
3101     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3102         "projection_type", spherical_metadata->projection_type,
3103         NULL);
3104   if (spherical_metadata->stereo_mode)
3105     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
3106         "stereo_mode", spherical_metadata->stereo_mode,
3107         NULL);
3108
3109   gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
3110           gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
3111                   gst_tag_list_copy (taglist)));
3112
3113   gst_tag_list_unref(taglist);
3114
3115   return;
3116 }
3117
3118 static void
3119 qtdemux_parse_SA3D (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3120 {
3121   guint offset = 0;
3122
3123   guint8 version = 0;
3124   guint8 ambisonic_type  = 0;
3125   guint32 ambisonic_order = 0;
3126   guint8 ambisonic_channel_ordering = 0;
3127   guint8 ambisonic_normalization = 0;
3128   guint32 num_channels = 0;
3129   guint32 channel_map[49] = { 0 };      /* Up to 6th order */
3130
3131   int i;
3132
3133   GST_DEBUG_OBJECT (qtdemux, "qtdemux_parse_SA3D");
3134
3135   qtdemux->header_size += length;
3136   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3137
3138   if (length <= offset + 16) {
3139     GST_DEBUG_OBJECT (qtdemux, "SA3D atom is too short, skipping");
3140     return;
3141   }
3142
3143   version = QT_UINT8 (buffer + offset);
3144   ambisonic_type = QT_UINT8 (buffer + offset + 1);
3145   ambisonic_order = QT_UINT32 (buffer + offset + 2);
3146   ambisonic_channel_ordering = QT_UINT8 (buffer + offset + 6);
3147   ambisonic_normalization = QT_UINT8 (buffer + offset + 7);
3148   num_channels = QT_UINT32 (buffer + offset + 8);
3149   for (i = 0; i < num_channels; ++i)
3150     channel_map[i] = QT_UINT32 (buffer + offset + 12 + i * 4);
3151
3152   GST_DEBUG_OBJECT (qtdemux, "version: %d", version);
3153   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type: %d", ambisonic_type);
3154   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order: %d", ambisonic_order);
3155   GST_DEBUG_OBJECT (qtdemux, "ambisonic_channel_ordering: %d",
3156       ambisonic_channel_ordering);
3157   GST_DEBUG_OBJECT (qtdemux, "ambisonic_normalization: %d",
3158       ambisonic_normalization);
3159   GST_DEBUG_OBJECT (qtdemux, "num_channels: %d", num_channels);
3160   for (i = 0; i < num_channels; ++i)
3161     GST_DEBUG_OBJECT (qtdemux, "channel_map: %d", channel_map[i]);
3162
3163   if (version == RFC_AMBISONIC_SA3DBOX_VERSION_SUPPORTED) {
3164     if (ambisonic_type == RFC_AMBISONIC_TYPE_PERIPHONIC)
3165       spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_PERIPHONIC;
3166
3167     if (ambisonic_order == RFC_AMBISONIC_ORDER_FOA) {
3168       if (num_channels == 4) {
3169         spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_FOA;
3170
3171         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_ACN)
3172             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_SN3D)
3173             && (channel_map[0] == 0) && (channel_map[1] == 1)
3174             && (channel_map[2] == 2) && (channel_map[3] == 3))
3175           spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMBIX;
3176
3177         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_FUMA)
3178             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_FUMA)
3179             && (channel_map[0] == 0) && (channel_map[1] == 3)
3180             && (channel_map[2] == 1) && (channel_map[3] == 2))
3181           spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMB;
3182       }
3183     }
3184   }
3185
3186   return;
3187 }
3188 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
3189
3190 static void
3191 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
3192     guint offset)
3193 {
3194   GstByteReader br;
3195   guint8 version;
3196   guint32 flags = 0;
3197   guint i;
3198   guint8 iv_size = 8;
3199   QtDemuxStream *stream;
3200   GstStructure *structure;
3201   QtDemuxCencSampleSetInfo *ss_info = NULL;
3202   const gchar *system_id;
3203   gboolean uses_sub_sample_encryption = FALSE;
3204
3205   if (qtdemux->n_streams == 0)
3206     return;
3207
3208   stream = qtdemux->streams[0];
3209
3210   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
3211   if (!gst_structure_has_name (structure, "application/x-cenc")) {
3212     GST_WARNING_OBJECT (qtdemux,
3213         "Attempting PIFF box parsing on an unencrypted stream.");
3214     return;
3215   }
3216
3217   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
3218       G_TYPE_STRING, &system_id, NULL);
3219   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
3220
3221   stream->protected = TRUE;
3222   stream->protection_scheme_type = FOURCC_cenc;
3223
3224   if (!stream->protection_scheme_info)
3225     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
3226
3227   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3228
3229   if (ss_info->default_properties)
3230     gst_structure_free (ss_info->default_properties);
3231
3232   ss_info->default_properties =
3233       gst_structure_new ("application/x-cenc",
3234       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
3235
3236   if (ss_info->crypto_info) {
3237     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3238     g_ptr_array_free (ss_info->crypto_info, TRUE);
3239     ss_info->crypto_info = NULL;
3240   }
3241
3242   /* skip UUID */
3243   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
3244
3245   if (!gst_byte_reader_get_uint8 (&br, &version)) {
3246     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
3247     return;
3248   }
3249
3250   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
3251     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
3252     return;
3253   }
3254
3255   if ((flags & 0x000001)) {
3256     guint32 algorithm_id = 0;
3257     const guint8 *kid;
3258     GstBuffer *kid_buf;
3259     gboolean is_encrypted = TRUE;
3260
3261     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
3262       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
3263       return;
3264     }
3265
3266     algorithm_id >>= 8;
3267     if (algorithm_id == 0) {
3268       is_encrypted = FALSE;
3269     } else if (algorithm_id == 1) {
3270       /* FIXME: maybe store this in properties? */
3271       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
3272     } else if (algorithm_id == 2) {
3273       /* FIXME: maybe store this in properties? */
3274       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
3275     }
3276
3277     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
3278       return;
3279
3280     if (!gst_byte_reader_get_data (&br, 16, &kid))
3281       return;
3282
3283     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
3284     gst_buffer_fill (kid_buf, 0, kid, 16);
3285     if (ss_info->default_properties)
3286       gst_structure_free (ss_info->default_properties);
3287     ss_info->default_properties =
3288         gst_structure_new ("application/x-cenc",
3289         "iv_size", G_TYPE_UINT, iv_size,
3290         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
3291         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
3292     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
3293         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
3294     gst_buffer_unref (kid_buf);
3295   } else if ((flags & 0x000002)) {
3296     uses_sub_sample_encryption = TRUE;
3297   }
3298
3299   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
3300     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
3301     return;
3302   }
3303
3304   ss_info->crypto_info =
3305       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
3306       (GDestroyNotify) qtdemux_gst_structure_free);
3307
3308   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
3309     GstStructure *properties;
3310     guint8 *data;
3311     GstBuffer *buf;
3312
3313     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3314     if (properties == NULL) {
3315       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3316       return;
3317     }
3318
3319     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
3320       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
3321       gst_structure_free (properties);
3322       return;
3323     }
3324     buf = gst_buffer_new_wrapped (data, iv_size);
3325     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3326     gst_buffer_unref (buf);
3327
3328     if (uses_sub_sample_encryption) {
3329       guint16 n_subsamples;
3330
3331       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
3332           || n_subsamples == 0) {
3333         GST_ERROR_OBJECT (qtdemux,
3334             "failed to get subsample count for sample %u", i);
3335         gst_structure_free (properties);
3336         return;
3337       }
3338       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3339       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
3340         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3341             i);
3342         gst_structure_free (properties);
3343         return;
3344       }
3345       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3346       gst_structure_set (properties,
3347           "subsample_count", G_TYPE_UINT, n_subsamples,
3348           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3349       gst_buffer_unref (buf);
3350     } else {
3351       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3352     }
3353
3354     g_ptr_array_add (ss_info->crypto_info, properties);
3355   }
3356 }
3357
3358 static void
3359 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3360 {
3361   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
3362     0x97, 0xA9, 0x42, 0xE8,
3363     0x9C, 0x71, 0x99, 0x94,
3364     0x91, 0xE3, 0xAF, 0xAC
3365   };
3366   static const guint8 playready_uuid[] = {
3367     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
3368     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
3369   };
3370
3371   static const guint8 piff_sample_encryption_uuid[] = {
3372     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
3373     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
3374   };
3375
3376   guint offset;
3377
3378   /* counts as header data */
3379   qtdemux->header_size += length;
3380
3381   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3382
3383   if (length <= offset + 16) {
3384     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3385     return;
3386   }
3387
3388   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3389     GstBuffer *buf;
3390     GstTagList *taglist;
3391
3392     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3393         length - offset - 16, NULL);
3394     taglist = gst_tag_list_from_xmp_buffer (buf);
3395     gst_buffer_unref (buf);
3396
3397     /* make sure we have a usable taglist */
3398     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3399
3400     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3401
3402   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3403     int len;
3404     const gunichar2 *s_utf16;
3405     char *contents;
3406
3407     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3408     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3409     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3410     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3411
3412     g_free (contents);
3413
3414     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3415         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3416         (NULL));
3417   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3418     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3419   } else {
3420     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3421         GST_READ_UINT32_LE (buffer + offset),
3422         GST_READ_UINT32_LE (buffer + offset + 4),
3423         GST_READ_UINT32_LE (buffer + offset + 8),
3424         GST_READ_UINT32_LE (buffer + offset + 12));
3425   }
3426 }
3427
3428 static void
3429 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3430 {
3431   GstSidxParser sidx_parser;
3432   GstIsoffParserResult res;
3433   guint consumed;
3434
3435   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3436
3437   res =
3438       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3439       &consumed);
3440   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3441   if (res == GST_ISOFF_QT_PARSER_DONE) {
3442     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3443   }
3444   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3445 }
3446
3447 /* caller verifies at least 8 bytes in buf */
3448 static void
3449 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3450     guint64 * plength, guint32 * pfourcc)
3451 {
3452   guint64 length;
3453   guint32 fourcc;
3454
3455   length = QT_UINT32 (data);
3456   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3457   fourcc = QT_FOURCC (data + 4);
3458   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3459
3460   if (length == 0) {
3461     length = G_MAXUINT64;
3462   } else if (length == 1 && size >= 16) {
3463     /* this means we have an extended size, which is the 64 bit value of
3464      * the next 8 bytes */
3465     length = QT_UINT64 (data + 8);
3466     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3467   }
3468
3469   if (plength)
3470     *plength = length;
3471   if (pfourcc)
3472     *pfourcc = fourcc;
3473 }
3474
3475 static gboolean
3476 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3477 {
3478   guint32 version = 0;
3479   GstClockTime duration = 0;
3480
3481   if (!gst_byte_reader_get_uint32_be (br, &version))
3482     goto failed;
3483
3484   version >>= 24;
3485   if (version == 1) {
3486     if (!gst_byte_reader_get_uint64_be (br, &duration))
3487       goto failed;
3488   } else {
3489     guint32 dur = 0;
3490
3491     if (!gst_byte_reader_get_uint32_be (br, &dur))
3492       goto failed;
3493     duration = dur;
3494   }
3495
3496   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3497   qtdemux->duration = duration;
3498
3499   return TRUE;
3500
3501 failed:
3502   {
3503     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3504     return FALSE;
3505   }
3506 }
3507
3508 static gboolean
3509 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3510     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3511 {
3512   if (!stream->parsed_trex && qtdemux->moov_node) {
3513     GNode *mvex, *trex;
3514     GstByteReader trex_data;
3515
3516     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3517     if (mvex) {
3518       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3519           &trex_data);
3520       while (trex) {
3521         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3522
3523         /* skip version/flags */
3524         if (!gst_byte_reader_skip (&trex_data, 4))
3525           goto next;
3526         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3527           goto next;
3528         if (id != stream->track_id)
3529           goto next;
3530         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3531           goto next;
3532         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3533           goto next;
3534         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3535           goto next;
3536         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3537           goto next;
3538
3539         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3540             "duration %d,  size %d, flags 0x%x", stream->track_id,
3541             dur, size, flags);
3542
3543         stream->parsed_trex = TRUE;
3544         stream->def_sample_description_index = sdi;
3545         stream->def_sample_duration = dur;
3546         stream->def_sample_size = size;
3547         stream->def_sample_flags = flags;
3548
3549       next:
3550         /* iterate all siblings */
3551         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3552             &trex_data);
3553       }
3554     }
3555   }
3556
3557   *ds_duration = stream->def_sample_duration;
3558   *ds_size = stream->def_sample_size;
3559   *ds_flags = stream->def_sample_flags;
3560
3561   /* even then, above values are better than random ... */
3562   if (G_UNLIKELY (!stream->parsed_trex)) {
3563     GST_WARNING_OBJECT (qtdemux,
3564         "failed to find fragment defaults for stream %d", stream->track_id);
3565     return FALSE;
3566   }
3567
3568   return TRUE;
3569 }
3570
3571 /* This method should be called whenever a more accurate duration might
3572  * have been found. It will update all relevant variables if/where needed
3573  */
3574 static void
3575 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3576 {
3577   guint i;
3578   guint64 movdur;
3579   GstClockTime prevdur;
3580
3581   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3582
3583   if (movdur > qtdemux->duration) {
3584     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3585     GST_DEBUG_OBJECT (qtdemux,
3586         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3587         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3588     qtdemux->duration = movdur;
3589     GST_DEBUG_OBJECT (qtdemux,
3590         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3591         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3592         GST_TIME_ARGS (qtdemux->segment.stop));
3593     if (qtdemux->segment.duration == prevdur) {
3594       /* If the current segment has duration/stop identical to previous duration
3595        * update them also (because they were set at that point in time with
3596        * the wrong duration */
3597       /* We convert the value *from* the timescale version to avoid rounding errors */
3598       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3599       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3600       qtdemux->segment.duration = fixeddur;
3601       qtdemux->segment.stop = fixeddur;
3602     }
3603   }
3604   for (i = 0; i < qtdemux->n_streams; i++) {
3605     QtDemuxStream *stream = qtdemux->streams[i];
3606     if (stream) {
3607       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3608       if (movdur > stream->duration) {
3609         GST_DEBUG_OBJECT (qtdemux,
3610             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3611             GST_TIME_ARGS (duration));
3612         stream->duration = movdur;
3613         if (stream->dummy_segment) {
3614           /* Update all dummy values to new duration */
3615           stream->segments[0].stop_time = duration;
3616           stream->segments[0].duration = duration;
3617           stream->segments[0].media_stop = duration;
3618
3619           /* let downstream know we possibly have a new stop time */
3620           if (stream->segment_index != -1) {
3621             GstClockTime pos;
3622
3623             if (qtdemux->segment.rate >= 0) {
3624               pos = stream->segment.start;
3625             } else {
3626               pos = stream->segment.stop;
3627             }
3628
3629             gst_qtdemux_stream_update_segment (qtdemux, stream,
3630                 stream->segment_index, pos, NULL, NULL);
3631           }
3632         }
3633       }
3634     }
3635   }
3636 }
3637
3638 static gboolean
3639 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3640     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3641     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3642     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3643     gboolean has_tfdt)
3644 {
3645   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3646   guint64 timestamp;
3647   gint32 data_offset = 0;
3648   guint32 flags = 0, first_flags = 0, samples_count = 0;
3649   gint i;
3650   guint8 *data;
3651   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3652   QtDemuxSample *sample;
3653   gboolean ismv = FALSE;
3654   gint64 initial_offset;
3655
3656   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3657       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3658       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3659       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3660
3661   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3662     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3663     return TRUE;
3664   }
3665
3666   /* presence of stss or not can't really tell us much,
3667    * and flags and so on tend to be marginally reliable in these files */
3668   if (stream->subtype == FOURCC_soun) {
3669     GST_DEBUG_OBJECT (qtdemux,
3670         "sound track in fragmented file; marking all keyframes");
3671     stream->all_keyframe = TRUE;
3672   }
3673
3674   if (!gst_byte_reader_skip (trun, 1) ||
3675       !gst_byte_reader_get_uint24_be (trun, &flags))
3676     goto fail;
3677
3678   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3679     goto fail;
3680
3681   if (flags & TR_DATA_OFFSET) {
3682     /* note this is really signed */
3683     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3684       goto fail;
3685     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3686     /* default base offset = first byte of moof */
3687     if (*base_offset == -1) {
3688       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3689       *base_offset = moof_offset;
3690     }
3691     *running_offset = *base_offset + data_offset;
3692   } else {
3693     /* if no offset at all, that would mean data starts at moof start,
3694      * which is a bit wrong and is ismv crappy way, so compensate
3695      * assuming data is in mdat following moof */
3696     if (*base_offset == -1) {
3697       *base_offset = moof_offset + moof_length + 8;
3698       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3699       ismv = TRUE;
3700     }
3701     if (*running_offset == -1)
3702       *running_offset = *base_offset;
3703   }
3704
3705   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3706       *running_offset);
3707   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3708       data_offset, flags, samples_count);
3709
3710   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3711     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3712       GST_DEBUG_OBJECT (qtdemux,
3713           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3714       flags ^= TR_FIRST_SAMPLE_FLAGS;
3715     } else {
3716       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3717         goto fail;
3718       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3719     }
3720   }
3721
3722   /* FIXME ? spec says other bits should also be checked to determine
3723    * entry size (and prefix size for that matter) */
3724   entry_size = 0;
3725   dur_offset = size_offset = 0;
3726   if (flags & TR_SAMPLE_DURATION) {
3727     GST_LOG_OBJECT (qtdemux, "entry duration present");
3728     dur_offset = entry_size;
3729     entry_size += 4;
3730   }
3731   if (flags & TR_SAMPLE_SIZE) {
3732     GST_LOG_OBJECT (qtdemux, "entry size present");
3733     size_offset = entry_size;
3734     entry_size += 4;
3735   }
3736   if (flags & TR_SAMPLE_FLAGS) {
3737     GST_LOG_OBJECT (qtdemux, "entry flags present");
3738     flags_offset = entry_size;
3739     entry_size += 4;
3740   }
3741   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3742     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3743     ct_offset = entry_size;
3744     entry_size += 4;
3745   }
3746
3747   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3748     goto fail;
3749   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3750
3751   if (stream->n_samples + samples_count >=
3752       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3753     goto index_too_big;
3754
3755   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3756       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3757       (stream->n_samples + samples_count) *
3758       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3759
3760   /* create a new array of samples if it's the first sample parsed */
3761   if (stream->n_samples == 0) {
3762     g_assert (stream->samples == NULL);
3763     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3764     /* or try to reallocate it with space enough to insert the new samples */
3765   } else
3766     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3767         stream->n_samples + samples_count);
3768   if (stream->samples == NULL)
3769     goto out_of_memory;
3770
3771   if (qtdemux->fragment_start != -1) {
3772     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3773     qtdemux->fragment_start = -1;
3774   } else {
3775     if (stream->n_samples == 0) {
3776       if (decode_ts > 0) {
3777         timestamp = decode_ts;
3778       } else if (stream->pending_seek != NULL) {
3779         /* if we don't have a timestamp from a tfdt box, we'll use the one
3780          * from the mfra seek table */
3781         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3782             GST_TIME_ARGS (stream->pending_seek->ts));
3783
3784         /* FIXME: this is not fully correct, the timestamp refers to the random
3785          * access sample refered to in the tfra entry, which may not necessarily
3786          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3787         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3788       } else {
3789         timestamp = 0;
3790       }
3791
3792       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3793       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3794           GST_TIME_ARGS (gst_ts));
3795     } else {
3796       /* subsequent fragments extend stream */
3797       timestamp =
3798           stream->samples[stream->n_samples - 1].timestamp +
3799           stream->samples[stream->n_samples - 1].duration;
3800
3801       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3802        * difference (1 sec.) between decode_ts and timestamp, prefer the
3803        * former */
3804       if (has_tfdt && !qtdemux->upstream_format_is_time
3805           && ABSDIFF (decode_ts, timestamp) >
3806           MAX (stream->duration_last_moof / 2,
3807               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3808         GST_INFO_OBJECT (qtdemux,
3809             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3810             ") are significantly different (more than %" GST_TIME_FORMAT
3811             "), using decode_ts",
3812             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3813             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3814             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3815                     MAX (stream->duration_last_moof / 2,
3816                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3817         timestamp = decode_ts;
3818       }
3819
3820       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3821       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3822           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3823     }
3824   }
3825
3826   initial_offset = *running_offset;
3827
3828   sample = stream->samples + stream->n_samples;
3829   for (i = 0; i < samples_count; i++) {
3830     guint32 dur, size, sflags, ct;
3831
3832     /* first read sample data */
3833     if (flags & TR_SAMPLE_DURATION) {
3834       dur = QT_UINT32 (data + dur_offset);
3835     } else {
3836       dur = d_sample_duration;
3837     }
3838     if (flags & TR_SAMPLE_SIZE) {
3839       size = QT_UINT32 (data + size_offset);
3840     } else {
3841       size = d_sample_size;
3842     }
3843     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3844       if (i == 0) {
3845         sflags = first_flags;
3846       } else {
3847         sflags = d_sample_flags;
3848       }
3849     } else if (flags & TR_SAMPLE_FLAGS) {
3850       sflags = QT_UINT32 (data + flags_offset);
3851     } else {
3852       sflags = d_sample_flags;
3853     }
3854     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3855       ct = QT_UINT32 (data + ct_offset);
3856     } else {
3857       ct = 0;
3858     }
3859     data += entry_size;
3860
3861     /* fill the sample information */
3862     sample->offset = *running_offset;
3863     sample->pts_offset = ct;
3864     sample->size = size;
3865     sample->timestamp = timestamp;
3866     sample->duration = dur;
3867     /* sample-is-difference-sample */
3868     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3869      * now idea how it relates to bitfield other than massive LE/BE confusion */
3870     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3871     *running_offset += size;
3872     timestamp += dur;
3873     stream->duration_moof += dur;
3874     sample++;
3875   }
3876
3877   /* Update total duration if needed */
3878   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3879
3880   /* Pre-emptively figure out size of mdat based on trun information.
3881    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3882    * size, else we will still be able to use this when dealing with gap'ed
3883    * input */
3884   qtdemux->mdatleft = *running_offset - initial_offset;
3885   qtdemux->mdatoffset = initial_offset;
3886   qtdemux->mdatsize = qtdemux->mdatleft;
3887
3888   stream->n_samples += samples_count;
3889   stream->n_samples_moof += samples_count;
3890
3891   if (stream->pending_seek != NULL)
3892     stream->pending_seek = NULL;
3893
3894   return TRUE;
3895
3896 fail:
3897   {
3898     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3899     return FALSE;
3900   }
3901 out_of_memory:
3902   {
3903     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3904         stream->n_samples);
3905     return FALSE;
3906   }
3907 index_too_big:
3908   {
3909     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3910         "be larger than %uMB (broken file?)", stream->n_samples,
3911         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3912     return FALSE;
3913   }
3914 }
3915
3916 /* find stream with @id */
3917 static inline QtDemuxStream *
3918 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3919 {
3920   QtDemuxStream *stream;
3921   gint i;
3922
3923   /* check */
3924   if (G_UNLIKELY (!id)) {
3925     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3926     return NULL;
3927   }
3928
3929   /* try to get it fast and simple */
3930   if (G_LIKELY (id <= qtdemux->n_streams)) {
3931     stream = qtdemux->streams[id - 1];
3932     if (G_LIKELY (stream->track_id == id))
3933       return stream;
3934   }
3935
3936   /* linear search otherwise */
3937   for (i = 0; i < qtdemux->n_streams; i++) {
3938     stream = qtdemux->streams[i];
3939     if (stream->track_id == id)
3940       return stream;
3941   }
3942   if (qtdemux->mss_mode) {
3943     /* mss should have only 1 stream anyway */
3944     return qtdemux->streams[0];
3945   }
3946
3947   return NULL;
3948 }
3949
3950 static gboolean
3951 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3952     guint32 * fragment_number)
3953 {
3954   if (!gst_byte_reader_skip (mfhd, 4))
3955     goto fail;
3956   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3957     goto fail;
3958   return TRUE;
3959 fail:
3960   {
3961     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3962     return FALSE;
3963   }
3964 }
3965
3966 static gboolean
3967 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3968     QtDemuxStream ** stream, guint32 * default_sample_duration,
3969     guint32 * default_sample_size, guint32 * default_sample_flags,
3970     gint64 * base_offset)
3971 {
3972   guint32 flags = 0;
3973   guint32 track_id = 0;
3974
3975   if (!gst_byte_reader_skip (tfhd, 1) ||
3976       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3977     goto invalid_track;
3978
3979   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3980     goto invalid_track;
3981
3982   *stream = qtdemux_find_stream (qtdemux, track_id);
3983   if (G_UNLIKELY (!*stream))
3984     goto unknown_stream;
3985
3986   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3987     *base_offset = qtdemux->moof_offset;
3988
3989   if (flags & TF_BASE_DATA_OFFSET)
3990     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3991       goto invalid_track;
3992
3993   /* obtain stream defaults */
3994   qtdemux_parse_trex (qtdemux, *stream,
3995       default_sample_duration, default_sample_size, default_sample_flags);
3996
3997   (*stream)->stsd_sample_description_id =
3998       (*stream)->def_sample_description_index - 1;
3999
4000   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
4001     guint32 sample_description_index;
4002     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
4003       goto invalid_track;
4004     (*stream)->stsd_sample_description_id = sample_description_index - 1;
4005   }
4006
4007   if (qtdemux->mss_mode) {
4008     /* mss has no stsd entry */
4009     (*stream)->stsd_sample_description_id = 0;
4010   }
4011
4012   if (flags & TF_DEFAULT_SAMPLE_DURATION)
4013     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
4014       goto invalid_track;
4015
4016   if (flags & TF_DEFAULT_SAMPLE_SIZE)
4017     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
4018       goto invalid_track;
4019
4020   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
4021     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
4022       goto invalid_track;
4023
4024   return TRUE;
4025
4026 invalid_track:
4027   {
4028     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
4029     return FALSE;
4030   }
4031 unknown_stream:
4032   {
4033     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
4034     return TRUE;
4035   }
4036 }
4037
4038 static gboolean
4039 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
4040     guint64 * decode_time)
4041 {
4042   guint32 version = 0;
4043
4044   if (!gst_byte_reader_get_uint32_be (br, &version))
4045     return FALSE;
4046
4047   version >>= 24;
4048   if (version == 1) {
4049     if (!gst_byte_reader_get_uint64_be (br, decode_time))
4050       goto failed;
4051   } else {
4052     guint32 dec_time = 0;
4053     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
4054       goto failed;
4055     *decode_time = dec_time;
4056   }
4057
4058   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
4059       *decode_time);
4060
4061   return TRUE;
4062
4063 failed:
4064   {
4065     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
4066     return FALSE;
4067   }
4068 }
4069
4070 /* Returns a pointer to a GstStructure containing the properties of
4071  * the stream sample identified by @sample_index. The caller must unref
4072  * the returned object after use. Returns NULL if unsuccessful. */
4073 static GstStructure *
4074 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
4075     QtDemuxStream * stream, guint sample_index)
4076 {
4077   QtDemuxCencSampleSetInfo *info = NULL;
4078
4079   g_return_val_if_fail (stream != NULL, NULL);
4080   g_return_val_if_fail (stream->protected, NULL);
4081   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
4082
4083   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4084
4085   /* Currently, cenc properties for groups of samples are not supported, so
4086    * simply return a copy of the default sample properties */
4087   return gst_structure_copy (info->default_properties);
4088 }
4089
4090 /* Parses the sizes of sample auxiliary information contained within a stream,
4091  * as given in a saiz box. Returns array of sample_count guint8 size values,
4092  * or NULL on failure */
4093 static guint8 *
4094 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
4095     GstByteReader * br, guint32 * sample_count)
4096 {
4097   guint32 flags = 0;
4098   guint8 *info_sizes;
4099   guint8 default_info_size;
4100
4101   g_return_val_if_fail (qtdemux != NULL, NULL);
4102   g_return_val_if_fail (stream != NULL, NULL);
4103   g_return_val_if_fail (br != NULL, NULL);
4104   g_return_val_if_fail (sample_count != NULL, NULL);
4105
4106   if (!gst_byte_reader_get_uint32_be (br, &flags))
4107     return NULL;
4108
4109   if (flags & 0x1) {
4110     /* aux_info_type and aux_info_type_parameter are ignored */
4111     if (!gst_byte_reader_skip (br, 8))
4112       return NULL;
4113   }
4114
4115   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
4116     return NULL;
4117   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
4118
4119   if (!gst_byte_reader_get_uint32_be (br, sample_count))
4120     return NULL;
4121   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
4122
4123
4124   if (default_info_size == 0) {
4125     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
4126       return NULL;
4127     }
4128   } else {
4129     info_sizes = g_new (guint8, *sample_count);
4130     memset (info_sizes, default_info_size, *sample_count);
4131   }
4132
4133   return info_sizes;
4134 }
4135
4136 /* Parses the offset of sample auxiliary information contained within a stream,
4137  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
4138 static gboolean
4139 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
4140     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
4141     guint64 * offset)
4142 {
4143   guint8 version = 0;
4144   guint32 flags = 0;
4145   guint32 aux_info_type = 0;
4146   guint32 aux_info_type_parameter = 0;
4147   guint32 entry_count;
4148   guint32 off_32;
4149   guint64 off_64;
4150   const guint8 *aux_info_type_data = NULL;
4151
4152   g_return_val_if_fail (qtdemux != NULL, FALSE);
4153   g_return_val_if_fail (stream != NULL, FALSE);
4154   g_return_val_if_fail (br != NULL, FALSE);
4155   g_return_val_if_fail (offset != NULL, FALSE);
4156
4157   if (!gst_byte_reader_get_uint8 (br, &version))
4158     return FALSE;
4159
4160   if (!gst_byte_reader_get_uint24_be (br, &flags))
4161     return FALSE;
4162
4163   if (flags & 0x1) {
4164
4165     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
4166       return FALSE;
4167     aux_info_type = QT_FOURCC (aux_info_type_data);
4168
4169     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
4170       return FALSE;
4171   } else if (stream->protected) {
4172     aux_info_type = stream->protection_scheme_type;
4173   } else {
4174     aux_info_type = CUR_STREAM (stream)->fourcc;
4175   }
4176
4177   if (info_type)
4178     *info_type = aux_info_type;
4179   if (info_type_parameter)
4180     *info_type_parameter = aux_info_type_parameter;
4181
4182   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
4183       "aux_info_type_parameter:  %#06x",
4184       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
4185
4186   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
4187     return FALSE;
4188
4189   if (entry_count != 1) {
4190     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
4191     return FALSE;
4192   }
4193
4194   if (version == 0) {
4195     if (!gst_byte_reader_get_uint32_be (br, &off_32))
4196       return FALSE;
4197     *offset = (guint64) off_32;
4198   } else {
4199     if (!gst_byte_reader_get_uint64_be (br, &off_64))
4200       return FALSE;
4201     *offset = off_64;
4202   }
4203
4204   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
4205   return TRUE;
4206 }
4207
4208 static void
4209 qtdemux_gst_structure_free (GstStructure * gststructure)
4210 {
4211   if (gststructure) {
4212     gst_structure_free (gststructure);
4213   }
4214 }
4215
4216 /* Parses auxiliary information relating to samples protected using Common
4217  * Encryption (cenc); the format of this information is defined in
4218  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
4219 static gboolean
4220 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
4221     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
4222 {
4223   QtDemuxCencSampleSetInfo *ss_info = NULL;
4224   guint8 size;
4225   gint i;
4226   GPtrArray *old_crypto_info = NULL;
4227   guint old_entries = 0;
4228
4229   g_return_val_if_fail (qtdemux != NULL, FALSE);
4230   g_return_val_if_fail (stream != NULL, FALSE);
4231   g_return_val_if_fail (br != NULL, FALSE);
4232   g_return_val_if_fail (stream->protected, FALSE);
4233   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
4234
4235   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4236
4237   if (ss_info->crypto_info) {
4238     old_crypto_info = ss_info->crypto_info;
4239     /* Count number of non-null entries remaining at the tail end */
4240     for (i = old_crypto_info->len - 1; i >= 0; i--) {
4241       if (g_ptr_array_index (old_crypto_info, i) == NULL)
4242         break;
4243       old_entries++;
4244     }
4245   }
4246
4247   ss_info->crypto_info =
4248       g_ptr_array_new_full (sample_count + old_entries,
4249       (GDestroyNotify) qtdemux_gst_structure_free);
4250
4251   /* We preserve old entries because we parse the next moof in advance
4252    * of consuming all samples from the previous moof, and otherwise
4253    * we'd discard the corresponding crypto info for the samples
4254    * from the previous fragment. */
4255   if (old_entries) {
4256     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
4257         old_entries);
4258     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
4259       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
4260               i));
4261       g_ptr_array_index (old_crypto_info, i) = NULL;
4262     }
4263   }
4264
4265   if (old_crypto_info) {
4266     /* Everything now belongs to the new array */
4267     g_ptr_array_free (old_crypto_info, TRUE);
4268   }
4269
4270   for (i = 0; i < sample_count; ++i) {
4271     GstStructure *properties;
4272     guint16 n_subsamples = 0;
4273     guint8 *data;
4274     guint iv_size;
4275     GstBuffer *buf;
4276
4277     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
4278     if (properties == NULL) {
4279       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
4280       return FALSE;
4281     }
4282     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
4283       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
4284       gst_structure_free (properties);
4285       return FALSE;
4286     }
4287     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
4288       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
4289       gst_structure_free (properties);
4290       return FALSE;
4291     }
4292     buf = gst_buffer_new_wrapped (data, iv_size);
4293     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
4294     gst_buffer_unref (buf);
4295     size = info_sizes[i];
4296     if (size > iv_size) {
4297       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4298           || !(n_subsamples > 0)) {
4299         gst_structure_free (properties);
4300         GST_ERROR_OBJECT (qtdemux,
4301             "failed to get subsample count for sample %u", i);
4302         return FALSE;
4303       }
4304       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4305       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4306         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4307             i);
4308         gst_structure_free (properties);
4309         return FALSE;
4310       }
4311       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4312       if (!buf) {
4313         gst_structure_free (properties);
4314         return FALSE;
4315       }
4316       gst_structure_set (properties,
4317           "subsample_count", G_TYPE_UINT, n_subsamples,
4318           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4319       gst_buffer_unref (buf);
4320     } else {
4321       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4322     }
4323     g_ptr_array_add (ss_info->crypto_info, properties);
4324   }
4325   return TRUE;
4326 }
4327
4328 /* Converts a UUID in raw byte form to a string representation, as defined in
4329  * RFC 4122. The caller takes ownership of the returned string and is
4330  * responsible for freeing it after use. */
4331 static gchar *
4332 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4333 {
4334   const guint8 *uuid = (const guint8 *) uuid_bytes;
4335
4336   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4337       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4338       uuid[0], uuid[1], uuid[2], uuid[3],
4339       uuid[4], uuid[5], uuid[6], uuid[7],
4340       uuid[8], uuid[9], uuid[10], uuid[11],
4341       uuid[12], uuid[13], uuid[14], uuid[15]);
4342 }
4343
4344 /* Parses a Protection System Specific Header box (pssh), as defined in the
4345  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4346  * information needed by a specific content protection system in order to
4347  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4348  * otherwise. */
4349 static gboolean
4350 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4351 {
4352   gchar *sysid_string;
4353   guint32 pssh_size = QT_UINT32 (node->data);
4354   GstBuffer *pssh = NULL;
4355   GstEvent *event = NULL;
4356   guint32 parent_box_type;
4357   gint i;
4358
4359   if (G_UNLIKELY (pssh_size < 32U)) {
4360     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4361     return FALSE;
4362   }
4363
4364   sysid_string =
4365       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4366
4367   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4368
4369   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
4370   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4371       gst_buffer_get_size (pssh));
4372
4373   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4374
4375   /* Push an event containing the pssh box onto the queues of all streams. */
4376   event = gst_event_new_protection (sysid_string, pssh,
4377       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4378   for (i = 0; i < qtdemux->n_streams; ++i) {
4379     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
4380         gst_event_ref (event));
4381   }
4382   g_free (sysid_string);
4383   gst_event_unref (event);
4384   gst_buffer_unref (pssh);
4385   return TRUE;
4386 }
4387
4388 static gboolean
4389 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4390     guint64 moof_offset, QtDemuxStream * stream)
4391 {
4392   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4393   GNode *uuid_node;
4394   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4395   GNode *saiz_node, *saio_node, *pssh_node;
4396   GstByteReader saiz_data, saio_data;
4397   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4398   gint64 base_offset, running_offset;
4399   guint32 frag_num;
4400
4401   /* NOTE @stream ignored */
4402
4403   moof_node = g_node_new ((guint8 *) buffer);
4404   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4405   qtdemux_node_dump (qtdemux, moof_node);
4406
4407   /* Get fragment number from mfhd and check it's valid */
4408   mfhd_node =
4409       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4410   if (mfhd_node == NULL)
4411     goto missing_mfhd;
4412   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4413     goto fail;
4414   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4415
4416   /* unknown base_offset to start with */
4417   base_offset = running_offset = -1;
4418   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4419   while (traf_node) {
4420     guint64 decode_time = 0;
4421
4422     /* Fragment Header node */
4423     tfhd_node =
4424         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4425         &tfhd_data);
4426     if (!tfhd_node)
4427       goto missing_tfhd;
4428     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4429             &ds_size, &ds_flags, &base_offset))
4430       goto missing_tfhd;
4431
4432     /* The following code assumes at most a single set of sample auxiliary
4433      * data in the fragment (consisting of a saiz box and a corresponding saio
4434      * box); in theory, however, there could be multiple sets of sample
4435      * auxiliary data in a fragment. */
4436     saiz_node =
4437         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4438         &saiz_data);
4439     if (saiz_node) {
4440       guint32 info_type = 0;
4441       guint64 offset = 0;
4442       guint32 info_type_parameter = 0;
4443
4444       g_free (qtdemux->cenc_aux_info_sizes);
4445
4446       qtdemux->cenc_aux_info_sizes =
4447           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4448           &qtdemux->cenc_aux_sample_count);
4449       if (qtdemux->cenc_aux_info_sizes == NULL) {
4450         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4451         goto fail;
4452       }
4453       saio_node =
4454           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4455           &saio_data);
4456       if (!saio_node) {
4457         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4458         g_free (qtdemux->cenc_aux_info_sizes);
4459         qtdemux->cenc_aux_info_sizes = NULL;
4460         goto fail;
4461       }
4462
4463       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4464                   &info_type, &info_type_parameter, &offset))) {
4465         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4466         g_free (qtdemux->cenc_aux_info_sizes);
4467         qtdemux->cenc_aux_info_sizes = NULL;
4468         goto fail;
4469       }
4470       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4471         offset += (guint64) (base_offset - qtdemux->moof_offset);
4472       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4473         GstByteReader br;
4474         if (offset > length) {
4475           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4476           qtdemux->cenc_aux_info_offset = offset;
4477         } else {
4478           gst_byte_reader_init (&br, buffer + offset, length - offset);
4479           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4480                   qtdemux->cenc_aux_info_sizes,
4481                   qtdemux->cenc_aux_sample_count)) {
4482             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4483             g_free (qtdemux->cenc_aux_info_sizes);
4484             qtdemux->cenc_aux_info_sizes = NULL;
4485             goto fail;
4486           }
4487         }
4488       }
4489     }
4490
4491     tfdt_node =
4492         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4493         &tfdt_data);
4494     if (tfdt_node) {
4495       /* We'll use decode_time to interpolate timestamps
4496        * in case the input timestamps are missing */
4497       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4498
4499       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4500           " (%" GST_TIME_FORMAT ")", decode_time,
4501           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4502                   decode_time) : GST_CLOCK_TIME_NONE));
4503
4504       /* Discard the fragment buffer timestamp info to avoid using it.
4505        * Rely on tfdt instead as it is more accurate than the timestamp
4506        * that is fetched from a manifest/playlist and is usually
4507        * less accurate. */
4508       qtdemux->fragment_start = -1;
4509     }
4510
4511     if (G_UNLIKELY (!stream)) {
4512       /* we lost track of offset, we'll need to regain it,
4513        * but can delay complaining until later or avoid doing so altogether */
4514       base_offset = -2;
4515       goto next;
4516     }
4517     if (G_UNLIKELY (base_offset < -1))
4518       goto lost_offset;
4519
4520     if (qtdemux->upstream_format_is_time)
4521       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
4522
4523     /* initialise moof sample data */
4524     stream->n_samples_moof = 0;
4525     stream->duration_last_moof = stream->duration_moof;
4526     stream->duration_moof = 0;
4527
4528     /* Track Run node */
4529     trun_node =
4530         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4531         &trun_data);
4532     while (trun_node) {
4533       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4534           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4535           &running_offset, decode_time, (tfdt_node != NULL));
4536       /* iterate all siblings */
4537       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4538           &trun_data);
4539     }
4540
4541     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4542     if (uuid_node) {
4543       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4544       guint32 box_length = QT_UINT32 (uuid_buffer);
4545
4546       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4547     }
4548
4549     /* if no new base_offset provided for next traf,
4550      * base is end of current traf */
4551     base_offset = running_offset;
4552     running_offset = -1;
4553
4554     if (stream->n_samples_moof && stream->duration_moof)
4555       stream->new_caps = TRUE;
4556
4557   next:
4558     /* iterate all siblings */
4559     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4560   }
4561
4562   /* parse any protection system info */
4563   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4564   while (pssh_node) {
4565     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4566     qtdemux_parse_pssh (qtdemux, pssh_node);
4567     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4568   }
4569
4570   g_node_destroy (moof_node);
4571   return TRUE;
4572
4573 missing_tfhd:
4574   {
4575     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4576     goto fail;
4577   }
4578 missing_mfhd:
4579   {
4580     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4581     goto fail;
4582   }
4583 lost_offset:
4584   {
4585     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4586     goto fail;
4587   }
4588 fail:
4589   {
4590     g_node_destroy (moof_node);
4591     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4592         (_("This file is corrupt and cannot be played.")), (NULL));
4593     return FALSE;
4594   }
4595 }
4596
4597 #if 0
4598 /* might be used if some day we actually use mfra & co
4599  * for random access to fragments,
4600  * but that will require quite some modifications and much less relying
4601  * on a sample array */
4602 #endif
4603
4604 static gboolean
4605 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4606 {
4607   QtDemuxStream *stream;
4608   guint32 ver_flags, track_id, len, num_entries, i;
4609   guint value_size, traf_size, trun_size, sample_size;
4610   guint64 time = 0, moof_offset = 0;
4611 #if 0
4612   GstBuffer *buf = NULL;
4613   GstFlowReturn ret;
4614 #endif
4615   GstByteReader tfra;
4616
4617   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4618
4619   if (!gst_byte_reader_skip (&tfra, 8))
4620     return FALSE;
4621
4622   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4623     return FALSE;
4624
4625   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4626       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4627       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4628     return FALSE;
4629
4630   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4631
4632   stream = qtdemux_find_stream (qtdemux, track_id);
4633   if (stream == NULL)
4634     goto unknown_trackid;
4635
4636   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4637   sample_size = (len & 3) + 1;
4638   trun_size = ((len & 12) >> 2) + 1;
4639   traf_size = ((len & 48) >> 4) + 1;
4640
4641   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4642       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4643
4644   if (num_entries == 0)
4645     goto no_samples;
4646
4647   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4648           value_size + value_size + traf_size + trun_size + sample_size))
4649     goto corrupt_file;
4650
4651   g_free (stream->ra_entries);
4652   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4653   stream->n_ra_entries = num_entries;
4654
4655   for (i = 0; i < num_entries; i++) {
4656     qt_atom_parser_get_offset (&tfra, value_size, &time);
4657     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4658     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4659     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4660     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4661
4662     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4663
4664     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4665         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4666
4667     stream->ra_entries[i].ts = time;
4668     stream->ra_entries[i].moof_offset = moof_offset;
4669
4670     /* don't want to go through the entire file and read all moofs at startup */
4671 #if 0
4672     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4673     if (ret != GST_FLOW_OK)
4674       goto corrupt_file;
4675     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4676         moof_offset, stream);
4677     gst_buffer_unref (buf);
4678 #endif
4679   }
4680
4681   check_update_duration (qtdemux, time);
4682
4683   return TRUE;
4684
4685 /* ERRORS */
4686 unknown_trackid:
4687   {
4688     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4689     return FALSE;
4690   }
4691 corrupt_file:
4692   {
4693     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4694     return FALSE;
4695   }
4696 no_samples:
4697   {
4698     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4699     return FALSE;
4700   }
4701 }
4702
4703 static gboolean
4704 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4705 {
4706   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4707   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4708   GstBuffer *mfro = NULL, *mfra = NULL;
4709   GstFlowReturn flow;
4710   gboolean ret = FALSE;
4711   GNode *mfra_node, *tfra_node;
4712   guint64 mfra_offset = 0;
4713   guint32 fourcc, mfra_size;
4714   gint64 len;
4715
4716   /* query upstream size in bytes */
4717   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4718     goto size_query_failed;
4719
4720   /* mfro box should be at the very end of the file */
4721   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4722   if (flow != GST_FLOW_OK)
4723     goto exit;
4724
4725   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4726
4727   fourcc = QT_FOURCC (mfro_map.data + 4);
4728   if (fourcc != FOURCC_mfro)
4729     goto exit;
4730
4731   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4732   if (mfro_map.size < 16)
4733     goto invalid_mfro_size;
4734
4735   mfra_size = QT_UINT32 (mfro_map.data + 12);
4736   if (mfra_size >= len)
4737     goto invalid_mfra_size;
4738
4739   mfra_offset = len - mfra_size;
4740
4741   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4742       mfra_offset, mfra_size);
4743
4744   /* now get and parse mfra box */
4745   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4746   if (flow != GST_FLOW_OK)
4747     goto broken_file;
4748
4749   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4750
4751   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4752   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4753
4754   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4755
4756   while (tfra_node) {
4757     qtdemux_parse_tfra (qtdemux, tfra_node);
4758     /* iterate all siblings */
4759     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4760   }
4761   g_node_destroy (mfra_node);
4762
4763   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4764   ret = TRUE;
4765
4766 exit:
4767
4768   if (mfro) {
4769     if (mfro_map.memory != NULL)
4770       gst_buffer_unmap (mfro, &mfro_map);
4771     gst_buffer_unref (mfro);
4772   }
4773   if (mfra) {
4774     if (mfra_map.memory != NULL)
4775       gst_buffer_unmap (mfra, &mfra_map);
4776     gst_buffer_unref (mfra);
4777   }
4778   return ret;
4779
4780 /* ERRORS */
4781 size_query_failed:
4782   {
4783     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4784     goto exit;
4785   }
4786 invalid_mfro_size:
4787   {
4788     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4789     goto exit;
4790   }
4791 invalid_mfra_size:
4792   {
4793     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4794     goto exit;
4795   }
4796 broken_file:
4797   {
4798     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4799     goto exit;
4800   }
4801 }
4802
4803 static guint64
4804 add_offset (guint64 offset, guint64 advance)
4805 {
4806   /* Avoid 64-bit overflow by clamping */
4807   if (offset > G_MAXUINT64 - advance)
4808     return G_MAXUINT64;
4809   return offset + advance;
4810 }
4811
4812 static GstFlowReturn
4813 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4814 {
4815   guint64 length = 0;
4816   guint32 fourcc = 0;
4817   GstBuffer *buf = NULL;
4818   GstFlowReturn ret = GST_FLOW_OK;
4819   guint64 cur_offset = qtdemux->offset;
4820   GstMapInfo map;
4821
4822   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4823   if (G_UNLIKELY (ret != GST_FLOW_OK))
4824     goto beach;
4825   gst_buffer_map (buf, &map, GST_MAP_READ);
4826   if (G_LIKELY (map.size >= 8))
4827     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4828   gst_buffer_unmap (buf, &map);
4829   gst_buffer_unref (buf);
4830
4831   /* maybe we already got most we needed, so only consider this eof */
4832   if (G_UNLIKELY (length == 0)) {
4833     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4834         (_("Invalid atom size.")),
4835         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4836             GST_FOURCC_ARGS (fourcc)));
4837     ret = GST_FLOW_EOS;
4838     goto beach;
4839   }
4840
4841   switch (fourcc) {
4842     case FOURCC_moof:
4843       /* record for later parsing when needed */
4844       if (!qtdemux->moof_offset) {
4845         qtdemux->moof_offset = qtdemux->offset;
4846       }
4847       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4848         /* FIXME */
4849       } else {
4850         qtdemux->offset += length;      /* skip moof and keep going */
4851       }
4852       if (qtdemux->got_moov) {
4853         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4854         ret = GST_FLOW_EOS;
4855         goto beach;
4856       }
4857       break;
4858     case FOURCC_mdat:
4859     case FOURCC_free:
4860     case FOURCC_wide:
4861     case FOURCC_PICT:
4862     case FOURCC_pnot:
4863     {
4864       GST_LOG_OBJECT (qtdemux,
4865           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4866           GST_FOURCC_ARGS (fourcc), cur_offset);
4867       qtdemux->offset = add_offset (qtdemux->offset, length);
4868       break;
4869     }
4870     case FOURCC_moov:
4871     {
4872       GstBuffer *moov = NULL;
4873
4874       if (qtdemux->got_moov) {
4875         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4876         qtdemux->offset = add_offset (qtdemux->offset, length);
4877         goto beach;
4878       }
4879
4880       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4881       if (ret != GST_FLOW_OK)
4882         goto beach;
4883       gst_buffer_map (moov, &map, GST_MAP_READ);
4884
4885       if (length != map.size) {
4886         /* Some files have a 'moov' atom at the end of the file which contains
4887          * a terminal 'free' atom where the body of the atom is missing.
4888          * Check for, and permit, this special case.
4889          */
4890         if (map.size >= 8) {
4891           guint8 *final_data = map.data + (map.size - 8);
4892           guint32 final_length = QT_UINT32 (final_data);
4893           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4894
4895           if (final_fourcc == FOURCC_free
4896               && map.size + final_length - 8 == length) {
4897             /* Ok, we've found that special case. Allocate a new buffer with
4898              * that free atom actually present. */
4899             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4900             gst_buffer_fill (newmoov, 0, map.data, map.size);
4901             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4902             gst_buffer_unmap (moov, &map);
4903             gst_buffer_unref (moov);
4904             moov = newmoov;
4905             gst_buffer_map (moov, &map, GST_MAP_READ);
4906           }
4907         }
4908       }
4909
4910       if (length != map.size) {
4911         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4912             (_("This file is incomplete and cannot be played.")),
4913             ("We got less than expected (received %" G_GSIZE_FORMAT
4914                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4915                 (guint) length, cur_offset));
4916         gst_buffer_unmap (moov, &map);
4917         gst_buffer_unref (moov);
4918         ret = GST_FLOW_ERROR;
4919         goto beach;
4920       }
4921       qtdemux->offset += length;
4922
4923       qtdemux_parse_moov (qtdemux, map.data, length);
4924       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4925
4926       qtdemux_parse_tree (qtdemux);
4927       if (qtdemux->moov_node_compressed) {
4928         g_node_destroy (qtdemux->moov_node_compressed);
4929         g_free (qtdemux->moov_node->data);
4930       }
4931       qtdemux->moov_node_compressed = NULL;
4932       g_node_destroy (qtdemux->moov_node);
4933       qtdemux->moov_node = NULL;
4934       gst_buffer_unmap (moov, &map);
4935       gst_buffer_unref (moov);
4936       qtdemux->got_moov = TRUE;
4937
4938       break;
4939     }
4940     case FOURCC_ftyp:
4941     {
4942       GstBuffer *ftyp = NULL;
4943
4944       /* extract major brand; might come in handy for ISO vs QT issues */
4945       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4946       if (ret != GST_FLOW_OK)
4947         goto beach;
4948       qtdemux->offset += length;
4949       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4950       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4951       gst_buffer_unmap (ftyp, &map);
4952       gst_buffer_unref (ftyp);
4953       break;
4954     }
4955     case FOURCC_uuid:
4956     {
4957       GstBuffer *uuid = NULL;
4958
4959       /* uuid are extension atoms */
4960       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4961       if (ret != GST_FLOW_OK)
4962         goto beach;
4963       qtdemux->offset += length;
4964       gst_buffer_map (uuid, &map, GST_MAP_READ);
4965       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4966       gst_buffer_unmap (uuid, &map);
4967       gst_buffer_unref (uuid);
4968       break;
4969     }
4970     case FOURCC_sidx:
4971     {
4972       GstBuffer *sidx = NULL;
4973       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4974       if (ret != GST_FLOW_OK)
4975         goto beach;
4976       qtdemux->offset += length;
4977       gst_buffer_map (sidx, &map, GST_MAP_READ);
4978       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4979       gst_buffer_unmap (sidx, &map);
4980       gst_buffer_unref (sidx);
4981       break;
4982     }
4983     default:
4984     {
4985       GstBuffer *unknown = NULL;
4986
4987       GST_LOG_OBJECT (qtdemux,
4988           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4989           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4990           cur_offset);
4991       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4992       if (ret != GST_FLOW_OK)
4993         goto beach;
4994       gst_buffer_map (unknown, &map, GST_MAP_READ);
4995       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4996       gst_buffer_unmap (unknown, &map);
4997       gst_buffer_unref (unknown);
4998       qtdemux->offset += length;
4999       break;
5000     }
5001   }
5002
5003 beach:
5004   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
5005     /* digested all data, show what we have */
5006 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
5007     if (spherical_metadata)
5008       _send_message_to_bus (qtdemux, spherical_metadata);
5009 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
5010     qtdemux_prepare_streams (qtdemux);
5011     ret = qtdemux_expose_streams (qtdemux);
5012
5013     qtdemux->state = QTDEMUX_STATE_MOVIE;
5014     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
5015         qtdemux->state);
5016     return ret;
5017   }
5018   return ret;
5019 }
5020
5021 /* Seeks to the previous keyframe of the indexed stream and
5022  * aligns other streams with respect to the keyframe timestamp
5023  * of indexed stream. Only called in case of Reverse Playback
5024  */
5025 static GstFlowReturn
5026 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
5027 {
5028   guint8 n = 0;
5029   guint32 seg_idx = 0, k_index = 0;
5030   guint32 ref_seg_idx, ref_k_index;
5031   GstClockTime k_pos = 0, last_stop = 0;
5032   QtDemuxSegment *seg = NULL;
5033   QtDemuxStream *ref_str = NULL;
5034   guint64 seg_media_start_mov;  /* segment media start time in mov format */
5035   guint64 target_ts;
5036
5037   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
5038    * and finally align all the other streams on that timestamp with their
5039    * respective keyframes */
5040   for (n = 0; n < qtdemux->n_streams; n++) {
5041     QtDemuxStream *str = qtdemux->streams[n];
5042
5043     /* No candidate yet, take the first stream */
5044     if (!ref_str) {
5045       ref_str = str;
5046       continue;
5047     }
5048
5049     /* So that stream has a segment, we prefer video streams */
5050     if (str->subtype == FOURCC_vide) {
5051       ref_str = str;
5052       break;
5053     }
5054   }
5055
5056   if (G_UNLIKELY (!ref_str)) {
5057     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
5058     goto eos;
5059   }
5060
5061   if (G_UNLIKELY (!ref_str->from_sample)) {
5062     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
5063     goto eos;
5064   }
5065
5066   /* So that stream has been playing from from_sample to to_sample. We will
5067    * get the timestamp of the previous sample and search for a keyframe before
5068    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
5069   if (ref_str->subtype == FOURCC_vide) {
5070     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
5071         ref_str->from_sample - 1, FALSE);
5072   } else {
5073     if (ref_str->from_sample >= 10)
5074       k_index = ref_str->from_sample - 10;
5075     else
5076       k_index = 0;
5077   }
5078
5079   target_ts =
5080       ref_str->samples[k_index].timestamp +
5081       ref_str->samples[k_index].pts_offset;
5082
5083   /* get current segment for that stream */
5084   seg = &ref_str->segments[ref_str->segment_index];
5085   /* Use segment start in original timescale for comparisons */
5086   seg_media_start_mov = seg->trak_media_start;
5087
5088   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
5089       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
5090       k_index, target_ts, seg_media_start_mov,
5091       GST_TIME_ARGS (seg->media_start));
5092
5093   /* Crawl back through segments to find the one containing this I frame */
5094   while (target_ts < seg_media_start_mov) {
5095     GST_DEBUG_OBJECT (qtdemux,
5096         "keyframe position (sample %u) is out of segment %u " " target %"
5097         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
5098         ref_str->segment_index, target_ts, seg_media_start_mov);
5099
5100     if (G_UNLIKELY (!ref_str->segment_index)) {
5101       /* Reached first segment, let's consider it's EOS */
5102       goto eos;
5103     }
5104     ref_str->segment_index--;
5105     seg = &ref_str->segments[ref_str->segment_index];
5106     /* Use segment start in original timescale for comparisons */
5107     seg_media_start_mov = seg->trak_media_start;
5108   }
5109   /* Calculate time position of the keyframe and where we should stop */
5110   k_pos =
5111       QTSTREAMTIME_TO_GSTTIME (ref_str,
5112       target_ts - seg->trak_media_start) + seg->time;
5113   last_stop =
5114       QTSTREAMTIME_TO_GSTTIME (ref_str,
5115       ref_str->samples[ref_str->from_sample].timestamp -
5116       seg->trak_media_start) + seg->time;
5117
5118   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
5119       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
5120       k_index, GST_TIME_ARGS (k_pos));
5121
5122   /* Set last_stop with the keyframe timestamp we pushed of that stream */
5123   qtdemux->segment.position = last_stop;
5124   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
5125       GST_TIME_ARGS (last_stop));
5126
5127   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
5128     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
5129     goto eos;
5130   }
5131
5132   ref_seg_idx = ref_str->segment_index;
5133   ref_k_index = k_index;
5134
5135   /* Align them all on this */
5136   for (n = 0; n < qtdemux->n_streams; n++) {
5137     guint32 index = 0;
5138     GstClockTime seg_time = 0;
5139     QtDemuxStream *str = qtdemux->streams[n];
5140
5141     /* aligning reference stream again might lead to backing up to yet another
5142      * keyframe (due to timestamp rounding issues),
5143      * potentially putting more load on downstream; so let's try to avoid */
5144     if (str == ref_str) {
5145       seg_idx = ref_seg_idx;
5146       seg = &str->segments[seg_idx];
5147       k_index = ref_k_index;
5148       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
5149           "sample at index %d", n, ref_str->segment_index, k_index);
5150     } else {
5151       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
5152       GST_DEBUG_OBJECT (qtdemux,
5153           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
5154           seg_idx, GST_TIME_ARGS (k_pos));
5155
5156       /* get segment and time in the segment */
5157       seg = &str->segments[seg_idx];
5158       seg_time = k_pos - seg->time;
5159
5160       /* get the media time in the segment.
5161        * No adjustment for empty "filler" segments */
5162       if (seg->media_start != GST_CLOCK_TIME_NONE)
5163         seg_time += seg->media_start;
5164
5165       /* get the index of the sample with media time */
5166       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
5167       GST_DEBUG_OBJECT (qtdemux,
5168           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
5169           GST_TIME_ARGS (seg_time), index);
5170
5171       /* find previous keyframe */
5172       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
5173     }
5174
5175     /* Remember until where we want to go */
5176     str->to_sample = str->from_sample - 1;
5177     /* Define our time position */
5178     target_ts =
5179         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
5180     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
5181     if (seg->media_start != GST_CLOCK_TIME_NONE)
5182       str->time_position -= seg->media_start;
5183
5184     /* Now seek back in time */
5185     gst_qtdemux_move_stream (qtdemux, str, k_index);
5186     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
5187         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
5188         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
5189   }
5190
5191   return GST_FLOW_OK;
5192
5193 eos:
5194   return GST_FLOW_EOS;
5195 }
5196
5197 /*
5198  * Gets the current qt segment start, stop and position for the
5199  * given time offset. This is used in update_segment()
5200  */
5201 static void
5202 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5203     QtDemuxStream * stream, GstClockTime offset,
5204     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5205 {
5206   GstClockTime seg_time;
5207   GstClockTime start, stop, time;
5208   QtDemuxSegment *segment;
5209
5210   segment = &stream->segments[stream->segment_index];
5211
5212   /* get time in this segment */
5213   seg_time = (offset - segment->time) * segment->rate;
5214
5215   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5216       GST_TIME_ARGS (seg_time));
5217
5218   if (G_UNLIKELY (seg_time > segment->duration)) {
5219     GST_LOG_OBJECT (stream->pad,
5220         "seg_time > segment->duration %" GST_TIME_FORMAT,
5221         GST_TIME_ARGS (segment->duration));
5222     seg_time = segment->duration;
5223   }
5224
5225   /* qtdemux->segment.stop is in outside-time-realm, whereas
5226    * segment->media_stop is in track-time-realm.
5227    *
5228    * In order to compare the two, we need to bring segment.stop
5229    * into the track-time-realm
5230    *
5231    * FIXME - does this comment still hold? Don't see any conversion here */
5232
5233   stop = qtdemux->segment.stop;
5234   if (stop == GST_CLOCK_TIME_NONE)
5235     stop = qtdemux->segment.duration;
5236   if (stop == GST_CLOCK_TIME_NONE)
5237     stop = segment->media_stop;
5238   else
5239     stop =
5240         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5241
5242   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5243     start = segment->time + seg_time;
5244     time = offset;
5245     stop = start - seg_time + segment->duration;
5246   } else if (qtdemux->segment.rate >= 0) {
5247     start = MIN (segment->media_start + seg_time, stop);
5248     time = offset;
5249   } else {
5250     if (segment->media_start >= qtdemux->segment.start) {
5251       time = segment->time;
5252     } else {
5253       time = segment->time + (qtdemux->segment.start - segment->media_start);
5254     }
5255
5256     start = MAX (segment->media_start, qtdemux->segment.start);
5257     stop = MIN (segment->media_start + seg_time, stop);
5258   }
5259
5260   *_start = start;
5261   *_stop = stop;
5262   *_time = time;
5263 }
5264
5265 /*
5266  * Updates the qt segment used for the stream and pushes a new segment event
5267  * downstream on this stream's pad.
5268  */
5269 static gboolean
5270 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5271     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5272     GstClockTime * _stop)
5273 {
5274   QtDemuxSegment *segment;
5275   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5276   gdouble rate;
5277   GstEvent *event;
5278
5279   /* update the current segment */
5280   stream->segment_index = seg_idx;
5281
5282   /* get the segment */
5283   segment = &stream->segments[seg_idx];
5284
5285   if (G_UNLIKELY (offset < segment->time)) {
5286     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5287         GST_TIME_ARGS (segment->time));
5288     return FALSE;
5289   }
5290
5291   /* segment lies beyond total indicated duration */
5292   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5293           segment->time > qtdemux->segment.duration)) {
5294     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5295         " < segment->time %" GST_TIME_FORMAT,
5296         GST_TIME_ARGS (qtdemux->segment.duration),
5297         GST_TIME_ARGS (segment->time));
5298     return FALSE;
5299   }
5300
5301   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5302       &start, &stop, &time);
5303
5304   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5305       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5306       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5307
5308   /* combine global rate with that of the segment */
5309   rate = segment->rate * qtdemux->segment.rate;
5310
5311   /* Copy flags from main segment */
5312   stream->segment.flags = qtdemux->segment.flags;
5313
5314   /* update the segment values used for clipping */
5315   stream->segment.offset = qtdemux->segment.offset;
5316   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5317   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5318   stream->segment.rate = rate;
5319   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5320       stream->cslg_shift);
5321   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5322       stream->cslg_shift);
5323   stream->segment.time = time;
5324   stream->segment.position = stream->segment.start;
5325
5326   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5327       &stream->segment);
5328
5329   /* now prepare and send the segment */
5330   if (stream->pad) {
5331     event = gst_event_new_segment (&stream->segment);
5332     if (qtdemux->segment_seqnum) {
5333       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5334     }
5335     gst_pad_push_event (stream->pad, event);
5336     /* assume we can send more data now */
5337     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5338     /* clear to send tags on this pad now */
5339     gst_qtdemux_push_tags (qtdemux, stream);
5340   }
5341
5342   if (_start)
5343     *_start = start;
5344   if (_stop)
5345     *_stop = stop;
5346
5347   return TRUE;
5348 }
5349
5350 /* activate the given segment number @seg_idx of @stream at time @offset.
5351  * @offset is an absolute global position over all the segments.
5352  *
5353  * This will push out a NEWSEGMENT event with the right values and
5354  * position the stream index to the first decodable sample before
5355  * @offset.
5356  */
5357 static gboolean
5358 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5359     guint32 seg_idx, GstClockTime offset)
5360 {
5361   QtDemuxSegment *segment;
5362   guint32 index, kf_index;
5363   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5364
5365   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5366       seg_idx, GST_TIME_ARGS (offset));
5367
5368   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5369           &start, &stop))
5370     return FALSE;
5371
5372   segment = &stream->segments[stream->segment_index];
5373
5374   /* in the fragmented case, we pick a fragment that starts before our
5375    * desired position and rely on downstream to wait for a keyframe
5376    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5377    * tfra entries tells us which trun/sample the key unit is in, but we don't
5378    * make use of this additional information at the moment) */
5379   if (qtdemux->fragmented) {
5380     stream->to_sample = G_MAXUINT32;
5381     return TRUE;
5382   }
5383
5384   /* We don't need to look for a sample in push-based */
5385   if (!qtdemux->pullbased)
5386     return TRUE;
5387
5388   /* and move to the keyframe before the indicated media time of the
5389    * segment */
5390   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5391     if (qtdemux->segment.rate >= 0) {
5392       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5393       stream->to_sample = G_MAXUINT32;
5394       GST_DEBUG_OBJECT (stream->pad,
5395           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5396           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5397           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5398     } else {
5399       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5400       stream->to_sample = index;
5401       GST_DEBUG_OBJECT (stream->pad,
5402           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5403           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5404           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5405     }
5406   } else {
5407     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5408         "this is an empty segment");
5409     return TRUE;
5410   }
5411
5412   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5413    * encountered an error and printed a message so we return appropriately */
5414   if (index == -1)
5415     return FALSE;
5416
5417   /* we're at the right spot */
5418   if (index == stream->sample_index) {
5419     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5420     return TRUE;
5421   }
5422
5423   /* find keyframe of the target index */
5424   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5425
5426 /* *INDENT-OFF* */
5427 /* indent does stupid stuff with stream->samples[].timestamp */
5428
5429   /* if we move forwards, we don't have to go back to the previous
5430    * keyframe since we already sent that. We can also just jump to
5431    * the keyframe right before the target index if there is one. */
5432   if (index > stream->sample_index) {
5433     /* moving forwards check if we move past a keyframe */
5434     if (kf_index > stream->sample_index) {
5435       GST_DEBUG_OBJECT (stream->pad,
5436            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5437            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5438            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5439       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5440     } else {
5441       GST_DEBUG_OBJECT (stream->pad,
5442           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5443           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5444           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5445     }
5446   } else {
5447     GST_DEBUG_OBJECT (stream->pad,
5448         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5449         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5450         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5451     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5452   }
5453
5454 /* *INDENT-ON* */
5455
5456   return TRUE;
5457 }
5458
5459 /* prepare to get the current sample of @stream, getting essential values.
5460  *
5461  * This function will also prepare and send the segment when needed.
5462  *
5463  * Return FALSE if the stream is EOS.
5464  *
5465  * PULL-BASED
5466  */
5467 static gboolean
5468 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5469     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5470     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5471     gboolean * keyframe)
5472 {
5473   QtDemuxSample *sample;
5474   GstClockTime time_position;
5475   guint32 seg_idx;
5476
5477   g_return_val_if_fail (stream != NULL, FALSE);
5478
5479   time_position = stream->time_position;
5480   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5481     goto eos;
5482
5483   seg_idx = stream->segment_index;
5484   if (G_UNLIKELY (seg_idx == -1)) {
5485     /* find segment corresponding to time_position if we are looking
5486      * for a segment. */
5487     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5488   }
5489
5490   /* different segment, activate it, sample_index will be set. */
5491   if (G_UNLIKELY (stream->segment_index != seg_idx))
5492     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5493
5494   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5495                   segment_index]))) {
5496     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5497
5498     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5499         " prepare empty sample");
5500
5501     *empty = TRUE;
5502     *pts = *dts = time_position;
5503     *duration = seg->duration - (time_position - seg->time);
5504
5505     return TRUE;
5506   }
5507
5508   *empty = FALSE;
5509
5510   if (stream->sample_index == -1)
5511     stream->sample_index = 0;
5512
5513   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5514       stream->sample_index, stream->n_samples);
5515
5516   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5517     if (!qtdemux->fragmented)
5518       goto eos;
5519
5520     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5521     do {
5522       GstFlowReturn flow;
5523
5524       GST_OBJECT_LOCK (qtdemux);
5525       flow = qtdemux_add_fragmented_samples (qtdemux);
5526       GST_OBJECT_UNLOCK (qtdemux);
5527
5528       if (flow != GST_FLOW_OK)
5529         goto eos;
5530     }
5531     while (stream->sample_index >= stream->n_samples);
5532   }
5533
5534   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5535     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5536         stream->sample_index);
5537     return FALSE;
5538   }
5539
5540   /* now get the info for the sample we're at */
5541   sample = &stream->samples[stream->sample_index];
5542
5543   *dts = QTSAMPLE_DTS (stream, sample);
5544   *pts = QTSAMPLE_PTS (stream, sample);
5545   *offset = sample->offset;
5546   *size = sample->size;
5547   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5548   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5549
5550   return TRUE;
5551
5552   /* special cases */
5553 eos:
5554   {
5555     stream->time_position = GST_CLOCK_TIME_NONE;
5556     return FALSE;
5557   }
5558 }
5559
5560 /* move to the next sample in @stream.
5561  *
5562  * Moves to the next segment when needed.
5563  */
5564 static void
5565 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5566 {
5567   QtDemuxSample *sample;
5568   QtDemuxSegment *segment;
5569
5570   /* get current segment */
5571   segment = &stream->segments[stream->segment_index];
5572
5573   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5574     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5575     goto next_segment;
5576   }
5577
5578   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5579     /* Mark the stream as EOS */
5580     GST_DEBUG_OBJECT (qtdemux,
5581         "reached max allowed sample %u, mark EOS", stream->to_sample);
5582     stream->time_position = GST_CLOCK_TIME_NONE;
5583     return;
5584   }
5585
5586   /* move to next sample */
5587   stream->sample_index++;
5588   stream->offset_in_sample = 0;
5589
5590   /* reached the last sample, we need the next segment */
5591   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5592     goto next_segment;
5593
5594   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5595     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5596         stream->sample_index);
5597     return;
5598   }
5599
5600   /* get next sample */
5601   sample = &stream->samples[stream->sample_index];
5602
5603   /* see if we are past the segment */
5604   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5605     goto next_segment;
5606
5607   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5608     /* inside the segment, update time_position, looks very familiar to
5609      * GStreamer segments, doesn't it? */
5610     stream->time_position =
5611         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5612   } else {
5613     /* not yet in segment, time does not yet increment. This means
5614      * that we are still prerolling keyframes to the decoder so it can
5615      * decode the first sample of the segment. */
5616     stream->time_position = segment->time;
5617   }
5618   return;
5619
5620   /* move to the next segment */
5621 next_segment:
5622   {
5623     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5624
5625     if (stream->segment_index == stream->n_segments - 1) {
5626       /* are we at the end of the last segment, we're EOS */
5627       stream->time_position = GST_CLOCK_TIME_NONE;
5628     } else {
5629       /* else we're only at the end of the current segment */
5630       stream->time_position = segment->stop_time;
5631     }
5632     /* make sure we select a new segment */
5633
5634     /* accumulate previous segments */
5635     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5636       stream->accumulated_base +=
5637           (stream->segment.stop -
5638           stream->segment.start) / ABS (stream->segment.rate);
5639
5640     stream->segment_index = -1;
5641   }
5642 }
5643
5644 static void
5645 gst_qtdemux_sync_streams (GstQTDemux * demux)
5646 {
5647   gint i;
5648
5649   if (demux->n_streams <= 1)
5650     return;
5651
5652   for (i = 0; i < demux->n_streams; i++) {
5653     QtDemuxStream *stream;
5654     GstClockTime end_time;
5655
5656     stream = demux->streams[i];
5657
5658     if (!stream->pad)
5659       continue;
5660
5661     /* TODO advance time on subtitle streams here, if any some day */
5662
5663     /* some clips/trailers may have unbalanced streams at the end,
5664      * so send EOS on shorter stream to prevent stalling others */
5665
5666     /* do not mess with EOS if SEGMENT seeking */
5667     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5668       continue;
5669
5670     if (demux->pullbased) {
5671       /* loop mode is sample time based */
5672       if (!STREAM_IS_EOS (stream))
5673         continue;
5674     } else {
5675       /* push mode is byte position based */
5676       if (stream->n_samples &&
5677           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5678         continue;
5679     }
5680
5681     if (stream->sent_eos)
5682       continue;
5683
5684     /* only act if some gap */
5685     end_time = stream->segments[stream->n_segments - 1].stop_time;
5686     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5687         ", stream end: %" GST_TIME_FORMAT,
5688         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5689     if (GST_CLOCK_TIME_IS_VALID (end_time)
5690         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5691       GstEvent *event;
5692
5693       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5694           GST_PAD_NAME (stream->pad));
5695       stream->sent_eos = TRUE;
5696       event = gst_event_new_eos ();
5697       if (demux->segment_seqnum)
5698         gst_event_set_seqnum (event, demux->segment_seqnum);
5699       gst_pad_push_event (stream->pad, event);
5700     }
5701   }
5702 }
5703
5704 /* EOS and NOT_LINKED need to be combined. This means that we return:
5705  *
5706  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5707  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5708  */
5709 static GstFlowReturn
5710 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5711     GstFlowReturn ret)
5712 {
5713   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5714
5715   if (stream->pad)
5716     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5717         ret);
5718   else
5719     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5720
5721   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5722   return ret;
5723 }
5724
5725 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5726  * completely clipped
5727  *
5728  * Should be used only with raw buffers */
5729 static GstBuffer *
5730 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5731     GstBuffer * buf)
5732 {
5733   guint64 start, stop, cstart, cstop, diff;
5734   GstClockTime pts, duration;
5735   gsize size, osize;
5736   gint num_rate, denom_rate;
5737   gint frame_size;
5738   gboolean clip_data;
5739   guint offset;
5740
5741   osize = size = gst_buffer_get_size (buf);
5742   offset = 0;
5743
5744   /* depending on the type, setup the clip parameters */
5745   if (stream->subtype == FOURCC_soun) {
5746     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5747     num_rate = GST_SECOND;
5748     denom_rate = (gint) CUR_STREAM (stream)->rate;
5749     clip_data = TRUE;
5750   } else if (stream->subtype == FOURCC_vide) {
5751     frame_size = size;
5752     num_rate = CUR_STREAM (stream)->fps_n;
5753     denom_rate = CUR_STREAM (stream)->fps_d;
5754     clip_data = FALSE;
5755   } else
5756     goto wrong_type;
5757
5758   if (frame_size <= 0)
5759     goto bad_frame_size;
5760
5761   /* we can only clip if we have a valid pts */
5762   pts = GST_BUFFER_PTS (buf);
5763   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5764     goto no_pts;
5765
5766   duration = GST_BUFFER_DURATION (buf);
5767
5768   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5769     duration =
5770         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5771   }
5772
5773   start = pts;
5774   stop = start + duration;
5775
5776   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5777               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5778     goto clipped;
5779
5780   /* see if some clipping happened */
5781   diff = cstart - start;
5782   if (diff > 0) {
5783     pts += diff;
5784     duration -= diff;
5785
5786     if (clip_data) {
5787       /* bring clipped time to samples and to bytes */
5788       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5789       diff *= frame_size;
5790
5791       GST_DEBUG_OBJECT (qtdemux,
5792           "clipping start to %" GST_TIME_FORMAT " %"
5793           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5794
5795       offset = diff;
5796       size -= diff;
5797     }
5798   }
5799   diff = stop - cstop;
5800   if (diff > 0) {
5801     duration -= diff;
5802
5803     if (clip_data) {
5804       /* bring clipped time to samples and then to bytes */
5805       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5806       diff *= frame_size;
5807       GST_DEBUG_OBJECT (qtdemux,
5808           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5809           " bytes", GST_TIME_ARGS (cstop), diff);
5810       size -= diff;
5811     }
5812   }
5813
5814   if (offset != 0 || size != osize)
5815     gst_buffer_resize (buf, offset, size);
5816
5817   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5818   GST_BUFFER_PTS (buf) = pts;
5819   GST_BUFFER_DURATION (buf) = duration;
5820
5821   return buf;
5822
5823   /* dropped buffer */
5824 wrong_type:
5825   {
5826     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5827     return buf;
5828   }
5829 bad_frame_size:
5830   {
5831     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5832     return buf;
5833   }
5834 no_pts:
5835   {
5836     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5837     return buf;
5838   }
5839 clipped:
5840   {
5841     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5842     gst_buffer_unref (buf);
5843     return NULL;
5844   }
5845 }
5846
5847 static GstBuffer *
5848 gst_qtdemux_align_buffer (GstQTDemux * demux,
5849     GstBuffer * buffer, gsize alignment)
5850 {
5851   GstMapInfo map;
5852
5853   gst_buffer_map (buffer, &map, GST_MAP_READ);
5854
5855   if (map.size < sizeof (guintptr)) {
5856     gst_buffer_unmap (buffer, &map);
5857     return buffer;
5858   }
5859
5860   if (((guintptr) map.data) & (alignment - 1)) {
5861     GstBuffer *new_buffer;
5862     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5863
5864     new_buffer = gst_buffer_new_allocate (NULL,
5865         gst_buffer_get_size (buffer), &params);
5866
5867     /* Copy data "by hand", so ensure alignment is kept: */
5868     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5869
5870     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5871     GST_DEBUG_OBJECT (demux,
5872         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5873         alignment);
5874
5875     gst_buffer_unmap (buffer, &map);
5876     gst_buffer_unref (buffer);
5877
5878     return new_buffer;
5879   }
5880
5881   gst_buffer_unmap (buffer, &map);
5882   return buffer;
5883 }
5884
5885 /* the input buffer metadata must be writable,
5886  * but time/duration etc not yet set and need not be preserved */
5887 static GstBuffer *
5888 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5889     GstBuffer * buf)
5890 {
5891   GstMapInfo map;
5892   guint nsize = 0;
5893   gchar *str;
5894
5895   /* not many cases for now */
5896   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5897     /* send a one time dvd clut event */
5898     if (stream->pending_event && stream->pad)
5899       gst_pad_push_event (stream->pad, stream->pending_event);
5900     stream->pending_event = NULL;
5901   }
5902
5903   if (G_UNLIKELY (stream->subtype != FOURCC_text
5904           && stream->subtype != FOURCC_sbtl &&
5905           stream->subtype != FOURCC_subp)) {
5906     return buf;
5907   }
5908
5909   gst_buffer_map (buf, &map, GST_MAP_READ);
5910
5911   /* empty buffer is sent to terminate previous subtitle */
5912   if (map.size <= 2) {
5913     gst_buffer_unmap (buf, &map);
5914     gst_buffer_unref (buf);
5915     return NULL;
5916   }
5917   if (stream->subtype == FOURCC_subp) {
5918     /* That's all the processing needed for subpictures */
5919     gst_buffer_unmap (buf, &map);
5920     return buf;
5921   }
5922
5923   nsize = GST_READ_UINT16_BE (map.data);
5924   nsize = MIN (nsize, map.size - 2);
5925
5926   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5927       nsize, map.size);
5928
5929   /* takes care of UTF-8 validation or UTF-16 recognition,
5930    * no other encoding expected */
5931   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5932   gst_buffer_unmap (buf, &map);
5933   if (str) {
5934     gst_buffer_unref (buf);
5935     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5936   } else {
5937     /* this should not really happen unless the subtitle is corrupted */
5938     gst_buffer_unref (buf);
5939     buf = NULL;
5940   }
5941
5942   /* FIXME ? convert optional subsequent style info to markup */
5943
5944   return buf;
5945 }
5946
5947 /* Sets a buffer's attributes properly and pushes it downstream.
5948  * Also checks for additional actions and custom processing that may
5949  * need to be done first.
5950  */
5951 static GstFlowReturn
5952 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5953     QtDemuxStream * stream, GstBuffer * buf,
5954     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5955     gboolean keyframe, GstClockTime position, guint64 byte_position)
5956 {
5957   GstFlowReturn ret = GST_FLOW_OK;
5958
5959   /* offset the timestamps according to the edit list */
5960
5961   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5962     gchar *url;
5963     GstMapInfo map;
5964
5965     gst_buffer_map (buf, &map, GST_MAP_READ);
5966     url = g_strndup ((gchar *) map.data, map.size);
5967     gst_buffer_unmap (buf, &map);
5968     if (url != NULL && strlen (url) != 0) {
5969       /* we have RTSP redirect now */
5970       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5971           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5972               gst_structure_new ("redirect",
5973                   "new-location", G_TYPE_STRING, url, NULL)));
5974       qtdemux->posted_redirect = TRUE;
5975     } else {
5976       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5977           "posting");
5978     }
5979     g_free (url);
5980   }
5981
5982   /* position reporting */
5983   if (qtdemux->segment.rate >= 0) {
5984     qtdemux->segment.position = position;
5985     gst_qtdemux_sync_streams (qtdemux);
5986   }
5987
5988   if (G_UNLIKELY (!stream->pad)) {
5989     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5990     gst_buffer_unref (buf);
5991     goto exit;
5992   }
5993
5994   /* send out pending buffers */
5995   while (stream->buffers) {
5996     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5997
5998     if (G_UNLIKELY (stream->discont)) {
5999       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6000       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6001       stream->discont = FALSE;
6002     } else {
6003       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6004     }
6005
6006     if (stream->alignment > 1)
6007       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6008     gst_pad_push (stream->pad, buffer);
6009
6010     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6011   }
6012
6013   /* we're going to modify the metadata */
6014   buf = gst_buffer_make_writable (buf);
6015
6016   if (G_UNLIKELY (stream->need_process))
6017     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
6018
6019   if (!buf) {
6020     goto exit;
6021   }
6022
6023   GST_BUFFER_DTS (buf) = dts;
6024   GST_BUFFER_PTS (buf) = pts;
6025   GST_BUFFER_DURATION (buf) = duration;
6026   GST_BUFFER_OFFSET (buf) = -1;
6027   GST_BUFFER_OFFSET_END (buf) = -1;
6028
6029   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6030     gst_buffer_append_memory (buf,
6031         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6032
6033   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6034     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6035   }
6036 #if 0
6037   if (G_UNLIKELY (qtdemux->element_index)) {
6038     GstClockTime stream_time;
6039
6040     stream_time =
6041         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6042         timestamp);
6043     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6044       GST_LOG_OBJECT (qtdemux,
6045           "adding association %" GST_TIME_FORMAT "-> %"
6046           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6047       gst_index_add_association (qtdemux->element_index,
6048           qtdemux->index_id,
6049           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6050           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6051           GST_FORMAT_BYTES, byte_position, NULL);
6052     }
6053   }
6054 #endif
6055
6056   if (stream->need_clip)
6057     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6058
6059   if (G_UNLIKELY (buf == NULL))
6060     goto exit;
6061
6062   if (G_UNLIKELY (stream->discont)) {
6063     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6064     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6065     stream->discont = FALSE;
6066   } else {
6067     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6068   }
6069
6070   if (!keyframe) {
6071     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6072     stream->on_keyframe = FALSE;
6073   } else {
6074     stream->on_keyframe = TRUE;
6075   }
6076
6077
6078   GST_LOG_OBJECT (qtdemux,
6079       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6080       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
6081       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
6082       GST_PAD_NAME (stream->pad));
6083
6084   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
6085     GstStructure *crypto_info;
6086     QtDemuxCencSampleSetInfo *info =
6087         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6088     gint index;
6089     GstEvent *event;
6090
6091     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6092       gst_pad_push_event (stream->pad, event);
6093     }
6094
6095     if (info->crypto_info == NULL) {
6096       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
6097       gst_buffer_unref (buf);
6098       goto exit;
6099     }
6100
6101     /* The end of the crypto_info array matches our n_samples position,
6102      * so count backward from there */
6103     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6104     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6105       /* steal structure from array */
6106       crypto_info = g_ptr_array_index (info->crypto_info, index);
6107       g_ptr_array_index (info->crypto_info, index) = NULL;
6108       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6109           info->crypto_info->len);
6110       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6111         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
6112     } else {
6113       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6114           index, stream->sample_index);
6115     }
6116   }
6117
6118   if (stream->alignment > 1)
6119     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6120
6121   ret = gst_pad_push (stream->pad, buf);
6122
6123   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6124     /* mark position in stream, we'll need this to know when to send GAP event */
6125     stream->segment.position = pts + duration;
6126   }
6127
6128 exit:
6129   return ret;
6130 }
6131
6132 static const QtDemuxRandomAccessEntry *
6133 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6134     GstClockTime pos, gboolean after)
6135 {
6136   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6137   guint n_entries = stream->n_ra_entries;
6138   guint i;
6139
6140   /* we assume the table is sorted */
6141   for (i = 0; i < n_entries; ++i) {
6142     if (entries[i].ts > pos)
6143       break;
6144   }
6145
6146   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6147    * probably okay to assume that the index lists the very first fragment */
6148   if (i == 0)
6149     return &entries[0];
6150
6151   if (after)
6152     return &entries[i];
6153   else
6154     return &entries[i - 1];
6155 }
6156
6157 static gboolean
6158 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6159 {
6160   const QtDemuxRandomAccessEntry *best_entry = NULL;
6161   guint i;
6162
6163   GST_OBJECT_LOCK (qtdemux);
6164
6165   g_assert (qtdemux->n_streams > 0);
6166
6167   for (i = 0; i < qtdemux->n_streams; i++) {
6168     const QtDemuxRandomAccessEntry *entry;
6169     QtDemuxStream *stream;
6170     gboolean is_audio_or_video;
6171
6172     stream = qtdemux->streams[i];
6173
6174     g_free (stream->samples);
6175     stream->samples = NULL;
6176     stream->n_samples = 0;
6177     stream->stbl_index = -1;    /* no samples have yet been parsed */
6178     stream->sample_index = -1;
6179
6180     if (stream->protection_scheme_info) {
6181       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6182       if (stream->protection_scheme_type == FOURCC_cenc) {
6183         QtDemuxCencSampleSetInfo *info =
6184             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6185         if (info->crypto_info) {
6186           g_ptr_array_free (info->crypto_info, TRUE);
6187           info->crypto_info = NULL;
6188         }
6189       }
6190     }
6191
6192     if (stream->ra_entries == NULL)
6193       continue;
6194
6195     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6196       is_audio_or_video = TRUE;
6197     else
6198       is_audio_or_video = FALSE;
6199
6200     entry =
6201         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6202         stream->time_position, !is_audio_or_video);
6203
6204     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6205         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6206
6207     stream->pending_seek = entry;
6208
6209     /* decide position to jump to just based on audio/video tracks, not subs */
6210     if (!is_audio_or_video)
6211       continue;
6212
6213     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6214       best_entry = entry;
6215   }
6216
6217   if (best_entry == NULL) {
6218     GST_OBJECT_UNLOCK (qtdemux);
6219     return FALSE;
6220   }
6221
6222   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6223       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6224       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
6225       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6226
6227   qtdemux->moof_offset = best_entry->moof_offset;
6228
6229   qtdemux_add_fragmented_samples (qtdemux);
6230
6231   GST_OBJECT_UNLOCK (qtdemux);
6232   return TRUE;
6233 }
6234
6235 static GstFlowReturn
6236 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6237 {
6238   GstFlowReturn ret = GST_FLOW_OK;
6239   GstBuffer *buf = NULL;
6240   QtDemuxStream *stream;
6241   GstClockTime min_time;
6242   guint64 offset = 0;
6243   GstClockTime dts = GST_CLOCK_TIME_NONE;
6244   GstClockTime pts = GST_CLOCK_TIME_NONE;
6245   GstClockTime duration = 0;
6246   gboolean keyframe = FALSE;
6247   guint sample_size = 0;
6248   gboolean empty = 0;
6249   guint size;
6250   gint index;
6251   gint i;
6252
6253   gst_qtdemux_push_pending_newsegment (qtdemux);
6254
6255   if (qtdemux->fragmented_seek_pending) {
6256     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6257     gst_qtdemux_do_fragmented_seek (qtdemux);
6258     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6259     qtdemux->fragmented_seek_pending = FALSE;
6260   }
6261
6262   /* Figure out the next stream sample to output, min_time is expressed in
6263    * global time and runs over the edit list segments. */
6264   min_time = G_MAXUINT64;
6265   index = -1;
6266   for (i = 0; i < qtdemux->n_streams; i++) {
6267     GstClockTime position;
6268
6269     stream = qtdemux->streams[i];
6270     position = stream->time_position;
6271
6272     /* position of -1 is EOS */
6273     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6274       min_time = position;
6275       index = i;
6276     }
6277   }
6278   /* all are EOS */
6279   if (G_UNLIKELY (index == -1)) {
6280     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6281     goto eos;
6282   }
6283
6284   /* check for segment end */
6285   if (G_UNLIKELY (qtdemux->segment.stop != -1
6286           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6287               || (qtdemux->segment.rate < 0
6288                   && qtdemux->segment.start > min_time))
6289           && qtdemux->streams[index]->on_keyframe)) {
6290     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6291     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
6292     goto eos_stream;
6293   }
6294
6295   /* gap events for subtitle streams */
6296   for (i = 0; i < qtdemux->n_streams; i++) {
6297     stream = qtdemux->streams[i];
6298     if (stream->pad && (stream->subtype == FOURCC_subp
6299             || stream->subtype == FOURCC_text
6300             || stream->subtype == FOURCC_sbtl)) {
6301       /* send one second gap events until the stream catches up */
6302       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6303       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6304           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6305           stream->segment.position + GST_SECOND < min_time) {
6306         GstEvent *gap =
6307             gst_event_new_gap (stream->segment.position, GST_SECOND);
6308         gst_pad_push_event (stream->pad, gap);
6309         stream->segment.position += GST_SECOND;
6310       }
6311     }
6312   }
6313
6314   stream = qtdemux->streams[index];
6315   /* fetch info for the current sample of this stream */
6316   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6317               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6318     goto eos_stream;
6319
6320   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6321   if (stream->new_caps) {
6322     gst_qtdemux_configure_stream (qtdemux, stream);
6323     qtdemux_do_allocation (qtdemux, stream);
6324   }
6325
6326   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6327   if (G_UNLIKELY (qtdemux->
6328           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6329     if (stream->subtype == FOURCC_vide && !keyframe) {
6330       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
6331       goto next;
6332     }
6333   }
6334
6335   GST_DEBUG_OBJECT (qtdemux,
6336       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
6337       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6338       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
6339       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
6340
6341   if (G_UNLIKELY (empty)) {
6342     /* empty segment, push a gap and move to the next one */
6343     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6344     stream->segment.position = pts + duration;
6345     goto next;
6346   }
6347
6348   /* hmm, empty sample, skip and move to next sample */
6349   if (G_UNLIKELY (sample_size <= 0))
6350     goto next;
6351
6352   /* last pushed sample was out of boundary, goto next sample */
6353   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6354     goto next;
6355
6356   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6357     size = sample_size;
6358   } else {
6359     GST_DEBUG_OBJECT (qtdemux,
6360         "size %d larger than stream max_buffer_size %d, trimming",
6361         sample_size, stream->max_buffer_size);
6362     size =
6363         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6364   }
6365
6366   if (qtdemux->cenc_aux_info_offset > 0) {
6367     GstMapInfo map;
6368     GstByteReader br;
6369     GstBuffer *aux_info = NULL;
6370
6371     /* pull the data stored before the sample */
6372     ret =
6373         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6374         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6375     if (G_UNLIKELY (ret != GST_FLOW_OK))
6376       goto beach;
6377     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6378     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6379     gst_byte_reader_init (&br, map.data + 8, map.size);
6380     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6381             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6382       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6383       gst_buffer_unmap (aux_info, &map);
6384       gst_buffer_unref (aux_info);
6385       ret = GST_FLOW_ERROR;
6386       goto beach;
6387     }
6388     gst_buffer_unmap (aux_info, &map);
6389     gst_buffer_unref (aux_info);
6390   }
6391
6392   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6393       offset);
6394
6395   if (stream->use_allocator) {
6396     /* if we have a per-stream allocator, use it */
6397     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6398   }
6399
6400   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6401       size, &buf);
6402   if (G_UNLIKELY (ret != GST_FLOW_OK))
6403     goto beach;
6404
6405   if (size != sample_size) {
6406     pts += gst_util_uint64_scale_int (GST_SECOND,
6407         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6408         stream->timescale);
6409     dts +=
6410         gst_util_uint64_scale_int (GST_SECOND,
6411         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6412         stream->timescale);
6413     duration =
6414         gst_util_uint64_scale_int (GST_SECOND,
6415         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6416   }
6417
6418   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6419       dts, pts, duration, keyframe, min_time, offset);
6420
6421   if (size != sample_size) {
6422     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6423     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6424
6425     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6426         sample->timestamp +
6427         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6428     if (time_position >= segment->media_start) {
6429       /* inside the segment, update time_position, looks very familiar to
6430        * GStreamer segments, doesn't it? */
6431       stream->time_position = (time_position - segment->media_start) +
6432           segment->time;
6433     } else {
6434       /* not yet in segment, time does not yet increment. This means
6435        * that we are still prerolling keyframes to the decoder so it can
6436        * decode the first sample of the segment. */
6437       stream->time_position = segment->time;
6438     }
6439   }
6440
6441   /* combine flows */
6442   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6443   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6444    * we have no more data for the pad to push */
6445   if (ret == GST_FLOW_EOS)
6446     ret = GST_FLOW_OK;
6447
6448   stream->offset_in_sample += size;
6449   if (stream->offset_in_sample >= sample_size) {
6450     gst_qtdemux_advance_sample (qtdemux, stream);
6451   }
6452   goto beach;
6453
6454 next:
6455   gst_qtdemux_advance_sample (qtdemux, stream);
6456
6457 beach:
6458   return ret;
6459
6460   /* special cases */
6461 eos:
6462   {
6463     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6464     ret = GST_FLOW_EOS;
6465     goto beach;
6466   }
6467 eos_stream:
6468   {
6469     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6470     /* EOS will be raised if all are EOS */
6471     ret = GST_FLOW_OK;
6472     goto beach;
6473   }
6474 }
6475
6476 static void
6477 gst_qtdemux_loop (GstPad * pad)
6478 {
6479   GstQTDemux *qtdemux;
6480   guint64 cur_offset;
6481   GstFlowReturn ret;
6482
6483   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6484
6485   cur_offset = qtdemux->offset;
6486   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6487       cur_offset, qt_demux_state_string (qtdemux->state));
6488
6489   switch (qtdemux->state) {
6490     case QTDEMUX_STATE_INITIAL:
6491     case QTDEMUX_STATE_HEADER:
6492       ret = gst_qtdemux_loop_state_header (qtdemux);
6493       break;
6494     case QTDEMUX_STATE_MOVIE:
6495       ret = gst_qtdemux_loop_state_movie (qtdemux);
6496       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6497         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6498       }
6499       break;
6500     default:
6501       /* ouch */
6502       goto invalid_state;
6503   }
6504
6505   /* if something went wrong, pause */
6506   if (ret != GST_FLOW_OK)
6507     goto pause;
6508
6509 done:
6510   gst_object_unref (qtdemux);
6511   return;
6512
6513   /* ERRORS */
6514 invalid_state:
6515   {
6516     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6517         (NULL), ("streaming stopped, invalid state"));
6518     gst_pad_pause_task (pad);
6519     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6520     goto done;
6521   }
6522 pause:
6523   {
6524     const gchar *reason = gst_flow_get_name (ret);
6525
6526     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6527
6528     gst_pad_pause_task (pad);
6529
6530     /* fatal errors need special actions */
6531     /* check EOS */
6532     if (ret == GST_FLOW_EOS) {
6533       if (qtdemux->n_streams == 0) {
6534         /* we have no streams, post an error */
6535         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6536       }
6537       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6538         gint64 stop;
6539
6540         if ((stop = qtdemux->segment.stop) == -1)
6541           stop = qtdemux->segment.duration;
6542
6543         if (qtdemux->segment.rate >= 0) {
6544           GstMessage *message;
6545           GstEvent *event;
6546
6547           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6548           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6549               GST_FORMAT_TIME, stop);
6550           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6551           if (qtdemux->segment_seqnum) {
6552             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6553             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6554           }
6555           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6556           gst_qtdemux_push_event (qtdemux, event);
6557         } else {
6558           GstMessage *message;
6559           GstEvent *event;
6560
6561           /*  For Reverse Playback */
6562           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6563           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6564               GST_FORMAT_TIME, qtdemux->segment.start);
6565           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6566               qtdemux->segment.start);
6567           if (qtdemux->segment_seqnum) {
6568             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6569             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6570           }
6571           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6572           gst_qtdemux_push_event (qtdemux, event);
6573         }
6574       } else {
6575         GstEvent *event;
6576
6577         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6578         event = gst_event_new_eos ();
6579         if (qtdemux->segment_seqnum)
6580           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6581         gst_qtdemux_push_event (qtdemux, event);
6582       }
6583     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6584       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6585       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6586     }
6587     goto done;
6588   }
6589 }
6590
6591 /*
6592  * has_next_entry
6593  *
6594  * Returns if there are samples to be played.
6595  */
6596 static gboolean
6597 has_next_entry (GstQTDemux * demux)
6598 {
6599   QtDemuxStream *stream;
6600   int i;
6601
6602   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6603
6604   for (i = 0; i < demux->n_streams; i++) {
6605     stream = demux->streams[i];
6606
6607     if (stream->sample_index == -1) {
6608       stream->sample_index = 0;
6609       stream->offset_in_sample = 0;
6610     }
6611
6612     if (stream->sample_index >= stream->n_samples) {
6613       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6614       continue;
6615     }
6616     GST_DEBUG_OBJECT (demux, "Found a sample");
6617     return TRUE;
6618   }
6619
6620   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6621   return FALSE;
6622 }
6623
6624 /*
6625  * next_entry_size
6626  *
6627  * Returns the size of the first entry at the current offset.
6628  * If -1, there are none (which means EOS or empty file).
6629  */
6630 static guint64
6631 next_entry_size (GstQTDemux * demux)
6632 {
6633   QtDemuxStream *stream;
6634   int i;
6635   int smallidx = -1;
6636   guint64 smalloffs = (guint64) - 1;
6637   QtDemuxSample *sample;
6638
6639   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6640       demux->offset);
6641
6642   for (i = 0; i < demux->n_streams; i++) {
6643     stream = demux->streams[i];
6644
6645     if (stream->sample_index == -1) {
6646       stream->sample_index = 0;
6647       stream->offset_in_sample = 0;
6648     }
6649
6650     if (stream->sample_index >= stream->n_samples) {
6651       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6652       continue;
6653     }
6654
6655     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6656       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6657           stream->sample_index);
6658       return -1;
6659     }
6660
6661     sample = &stream->samples[stream->sample_index];
6662
6663     GST_LOG_OBJECT (demux,
6664         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6665         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6666         sample->offset, sample->size);
6667
6668     if (((smalloffs == -1)
6669             || (sample->offset < smalloffs)) && (sample->size)) {
6670       smallidx = i;
6671       smalloffs = sample->offset;
6672     }
6673   }
6674
6675   GST_LOG_OBJECT (demux,
6676       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6677       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6678
6679   if (smallidx == -1)
6680     return -1;
6681
6682   stream = demux->streams[smallidx];
6683   sample = &stream->samples[stream->sample_index];
6684
6685   if (sample->offset >= demux->offset) {
6686     demux->todrop = sample->offset - demux->offset;
6687     return sample->size + demux->todrop;
6688   }
6689
6690   GST_DEBUG_OBJECT (demux,
6691       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6692   return -1;
6693 }
6694
6695 static void
6696 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6697 {
6698   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6699
6700   gst_element_post_message (GST_ELEMENT_CAST (demux),
6701       gst_message_new_element (GST_OBJECT_CAST (demux),
6702           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6703 }
6704
6705 static gboolean
6706 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6707 {
6708   GstEvent *event;
6709   gboolean res = 0;
6710
6711   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6712
6713   event =
6714       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6715       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6716       GST_SEEK_TYPE_NONE, -1);
6717
6718   /* store seqnum to drop flush events, they don't need to reach downstream */
6719   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6720   res = gst_pad_push_event (demux->sinkpad, event);
6721   demux->offset_seek_seqnum = 0;
6722
6723   return res;
6724 }
6725
6726 /* check for seekable upstream, above and beyond a mere query */
6727 static void
6728 gst_qtdemux_check_seekability (GstQTDemux * demux)
6729 {
6730   GstQuery *query;
6731   gboolean seekable = FALSE;
6732   gint64 start = -1, stop = -1;
6733
6734   if (demux->upstream_size)
6735     return;
6736
6737   if (demux->upstream_format_is_time)
6738     return;
6739
6740   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6741   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6742     GST_DEBUG_OBJECT (demux, "seeking query failed");
6743     goto done;
6744   }
6745
6746   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6747
6748   /* try harder to query upstream size if we didn't get it the first time */
6749   if (seekable && stop == -1) {
6750     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6751     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6752   }
6753
6754   /* if upstream doesn't know the size, it's likely that it's not seekable in
6755    * practice even if it technically may be seekable */
6756   if (seekable && (start != 0 || stop <= start)) {
6757     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6758     seekable = FALSE;
6759   }
6760
6761 done:
6762   gst_query_unref (query);
6763
6764   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6765       G_GUINT64_FORMAT ")", seekable, start, stop);
6766   demux->upstream_seekable = seekable;
6767   demux->upstream_size = seekable ? stop : -1;
6768 }
6769
6770 static void
6771 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6772 {
6773   g_return_if_fail (bytes <= demux->todrop);
6774
6775   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6776   gst_adapter_flush (demux->adapter, bytes);
6777   demux->neededbytes -= bytes;
6778   demux->offset += bytes;
6779   demux->todrop -= bytes;
6780 }
6781
6782 static void
6783 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6784 {
6785   if (G_UNLIKELY (demux->pending_newsegment)) {
6786     gint i;
6787
6788     gst_qtdemux_push_pending_newsegment (demux);
6789     /* clear to send tags on all streams */
6790     for (i = 0; i < demux->n_streams; i++) {
6791       QtDemuxStream *stream;
6792       stream = demux->streams[i];
6793       gst_qtdemux_push_tags (demux, stream);
6794       if (CUR_STREAM (stream)->sparse) {
6795         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6796         gst_pad_push_event (stream->pad,
6797             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6798       }
6799     }
6800   }
6801 }
6802
6803 static void
6804 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6805     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6806 {
6807   GstClockTime ts, dur;
6808   GstEvent *gap;
6809
6810   ts = pos;
6811   dur =
6812       stream->segments[segment_index].duration - (pos -
6813       stream->segments[segment_index].time);
6814   gap = gst_event_new_gap (ts, dur);
6815   stream->time_position += dur;
6816
6817   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6818       "segment: %" GST_PTR_FORMAT, gap);
6819   gst_pad_push_event (stream->pad, gap);
6820 }
6821
6822 static void
6823 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6824     QtDemuxStream * stream)
6825 {
6826   gint i;
6827
6828   /* Push any initial gap segments before proceeding to the
6829    * 'real' data */
6830   for (i = 0; i < stream->n_segments; i++) {
6831     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6832
6833     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6834       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6835           stream->time_position);
6836     } else {
6837       /* Only support empty segment at the beginning followed by
6838        * one non-empty segment, this was checked when parsing the
6839        * edts atom, arriving here is unexpected */
6840       g_assert (i + 1 == stream->n_segments);
6841       break;
6842     }
6843   }
6844 }
6845
6846 static GstFlowReturn
6847 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6848 {
6849   GstQTDemux *demux;
6850
6851   demux = GST_QTDEMUX (parent);
6852
6853   GST_DEBUG_OBJECT (demux,
6854       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6855       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6856       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6857       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6858       gst_buffer_get_size (inbuf), demux->offset);
6859
6860   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6861     gboolean is_gap_input = FALSE;
6862     gint i;
6863
6864     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6865
6866     for (i = 0; i < demux->n_streams; i++) {
6867       demux->streams[i]->discont = TRUE;
6868     }
6869
6870     /* Check if we can land back on our feet in the case where upstream is
6871      * handling the seeking/pushing of samples with gaps in between (like
6872      * in the case of trick-mode DASH for example) */
6873     if (demux->upstream_format_is_time
6874         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6875       gint i;
6876       for (i = 0; i < demux->n_streams; i++) {
6877         guint32 res;
6878         GST_LOG_OBJECT (demux,
6879             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6880             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6881         res =
6882             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6883             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6884         if (res != -1) {
6885           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6886           GST_LOG_OBJECT (demux,
6887               "Checking if sample %d from stream %d is valid (offset:%"
6888               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6889               sample->offset, sample->size);
6890           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6891             GST_LOG_OBJECT (demux,
6892                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6893                 res);
6894             is_gap_input = TRUE;
6895             /* We can go back to standard playback mode */
6896             demux->state = QTDEMUX_STATE_MOVIE;
6897             /* Remember which sample this stream is at */
6898             demux->streams[i]->sample_index = res;
6899             /* Finally update all push-based values to the expected values */
6900             demux->neededbytes = demux->streams[i]->samples[res].size;
6901             demux->offset = GST_BUFFER_OFFSET (inbuf);
6902             demux->mdatleft =
6903                 demux->mdatsize - demux->offset + demux->mdatoffset;
6904             demux->todrop = 0;
6905           }
6906         }
6907       }
6908       if (!is_gap_input) {
6909         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6910         /* Reset state if it's a real discont */
6911         demux->neededbytes = 16;
6912         demux->state = QTDEMUX_STATE_INITIAL;
6913         demux->offset = GST_BUFFER_OFFSET (inbuf);
6914         gst_adapter_clear (demux->adapter);
6915       }
6916     }
6917     /* Reverse fragmented playback, need to flush all we have before
6918      * consuming a new fragment.
6919      * The samples array have the timestamps calculated by accumulating the
6920      * durations but this won't work for reverse playback of fragments as
6921      * the timestamps of a subsequent fragment should be smaller than the
6922      * previously received one. */
6923     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6924       gst_qtdemux_process_adapter (demux, TRUE);
6925       for (i = 0; i < demux->n_streams; i++)
6926         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6927     }
6928   }
6929
6930   gst_adapter_push (demux->adapter, inbuf);
6931
6932   GST_DEBUG_OBJECT (demux,
6933       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6934       demux->neededbytes, gst_adapter_available (demux->adapter));
6935
6936   return gst_qtdemux_process_adapter (demux, FALSE);
6937 }
6938
6939 static GstFlowReturn
6940 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6941 {
6942   GstFlowReturn ret = GST_FLOW_OK;
6943
6944   /* we never really mean to buffer that much */
6945   if (demux->neededbytes == -1) {
6946     goto eos;
6947   }
6948
6949   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6950       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6951
6952 #ifndef GST_DISABLE_GST_DEBUG
6953     {
6954       guint64 discont_offset, distance_from_discont;
6955
6956       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6957       distance_from_discont =
6958           gst_adapter_distance_from_discont (demux->adapter);
6959
6960       GST_DEBUG_OBJECT (demux,
6961           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6962           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6963           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6964           demux->offset, discont_offset, distance_from_discont);
6965     }
6966 #endif
6967
6968     switch (demux->state) {
6969       case QTDEMUX_STATE_INITIAL:{
6970         const guint8 *data;
6971         guint32 fourcc;
6972         guint64 size;
6973
6974         gst_qtdemux_check_seekability (demux);
6975
6976         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6977
6978         /* get fourcc/length, set neededbytes */
6979         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6980             &size, &fourcc);
6981         gst_adapter_unmap (demux->adapter);
6982         data = NULL;
6983         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6984             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6985         if (size == 0) {
6986           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6987               (_("This file is invalid and cannot be played.")),
6988               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6989                   GST_FOURCC_ARGS (fourcc)));
6990           ret = GST_FLOW_ERROR;
6991           break;
6992         }
6993         if (fourcc == FOURCC_mdat) {
6994           gint next_entry = next_entry_size (demux);
6995           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6996             /* we have the headers, start playback */
6997             demux->state = QTDEMUX_STATE_MOVIE;
6998             demux->neededbytes = next_entry;
6999             demux->mdatleft = size;
7000             demux->mdatsize = demux->mdatleft;
7001           } else {
7002             /* no headers yet, try to get them */
7003             guint bs;
7004             gboolean res;
7005             guint64 old, target;
7006
7007           buffer_data:
7008             old = demux->offset;
7009             target = old + size;
7010
7011             /* try to jump over the atom with a seek */
7012             /* only bother if it seems worth doing so,
7013              * and avoids possible upstream/server problems */
7014             if (demux->upstream_seekable &&
7015                 demux->upstream_size > 4 * (1 << 20)) {
7016               res = qtdemux_seek_offset (demux, target);
7017             } else {
7018               GST_DEBUG_OBJECT (demux, "skipping seek");
7019               res = FALSE;
7020             }
7021
7022             if (res) {
7023               GST_DEBUG_OBJECT (demux, "seek success");
7024               /* remember the offset fo the first mdat so we can seek back to it
7025                * after we have the headers */
7026               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7027                 demux->first_mdat = old;
7028                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7029                     demux->first_mdat);
7030               }
7031               /* seek worked, continue reading */
7032               demux->offset = target;
7033               demux->neededbytes = 16;
7034               demux->state = QTDEMUX_STATE_INITIAL;
7035             } else {
7036               /* seek failed, need to buffer */
7037               demux->offset = old;
7038               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7039               /* there may be multiple mdat (or alike) buffers */
7040               /* sanity check */
7041               if (demux->mdatbuffer)
7042                 bs = gst_buffer_get_size (demux->mdatbuffer);
7043               else
7044                 bs = 0;
7045               if (size + bs > 10 * (1 << 20))
7046                 goto no_moov;
7047               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7048               demux->neededbytes = size;
7049               if (!demux->mdatbuffer)
7050                 demux->mdatoffset = demux->offset;
7051             }
7052           }
7053         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7054           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7055               (_("This file is invalid and cannot be played.")),
7056               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7057                   GST_FOURCC_ARGS (fourcc), size));
7058           ret = GST_FLOW_ERROR;
7059           break;
7060         } else {
7061           /* this means we already started buffering and still no moov header,
7062            * let's continue buffering everything till we get moov */
7063           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7064                   || fourcc == FOURCC_moof))
7065             goto buffer_data;
7066           demux->neededbytes = size;
7067           demux->state = QTDEMUX_STATE_HEADER;
7068         }
7069         break;
7070       }
7071       case QTDEMUX_STATE_HEADER:{
7072         const guint8 *data;
7073         guint32 fourcc;
7074
7075         GST_DEBUG_OBJECT (demux, "In header");
7076
7077         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7078
7079         /* parse the header */
7080         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7081             &fourcc);
7082         if (fourcc == FOURCC_moov) {
7083           gint n;
7084
7085           /* in usual fragmented setup we could try to scan for more
7086            * and end up at the the moov (after mdat) again */
7087           if (demux->got_moov && demux->n_streams > 0 &&
7088               (!demux->fragmented
7089                   || demux->last_moov_offset == demux->offset)) {
7090             GST_DEBUG_OBJECT (demux,
7091                 "Skipping moov atom as we have (this) one already");
7092           } else {
7093             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7094
7095             if (demux->got_moov && demux->fragmented) {
7096               GST_DEBUG_OBJECT (demux,
7097                   "Got a second moov, clean up data from old one");
7098               if (demux->moov_node_compressed) {
7099                 g_node_destroy (demux->moov_node_compressed);
7100                 if (demux->moov_node)
7101                   g_free (demux->moov_node->data);
7102               }
7103               demux->moov_node_compressed = NULL;
7104               if (demux->moov_node)
7105                 g_node_destroy (demux->moov_node);
7106               demux->moov_node = NULL;
7107             } else {
7108               /* prepare newsegment to send when streaming actually starts */
7109               if (!demux->pending_newsegment) {
7110                 demux->pending_newsegment =
7111                     gst_event_new_segment (&demux->segment);
7112                 if (demux->segment_seqnum)
7113                   gst_event_set_seqnum (demux->pending_newsegment,
7114                       demux->segment_seqnum);
7115               }
7116             }
7117
7118             demux->last_moov_offset = demux->offset;
7119
7120             qtdemux_parse_moov (demux, data, demux->neededbytes);
7121             qtdemux_node_dump (demux, demux->moov_node);
7122             qtdemux_parse_tree (demux);
7123             qtdemux_prepare_streams (demux);
7124             if (!demux->got_moov)
7125               qtdemux_expose_streams (demux);
7126             else {
7127
7128               for (n = 0; n < demux->n_streams; n++) {
7129                 QtDemuxStream *stream = demux->streams[n];
7130
7131                 gst_qtdemux_configure_stream (demux, stream);
7132               }
7133             }
7134
7135             demux->got_moov = TRUE;
7136             gst_qtdemux_check_send_pending_segment (demux);
7137
7138             /* fragmented streams headers shouldn't contain edts atoms */
7139             if (!demux->fragmented) {
7140               for (n = 0; n < demux->n_streams; n++) {
7141                 gst_qtdemux_stream_send_initial_gap_segments (demux,
7142                     demux->streams[n]);
7143               }
7144             }
7145
7146             if (demux->moov_node_compressed) {
7147               g_node_destroy (demux->moov_node_compressed);
7148               g_free (demux->moov_node->data);
7149             }
7150             demux->moov_node_compressed = NULL;
7151             g_node_destroy (demux->moov_node);
7152             demux->moov_node = NULL;
7153             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7154           }
7155         } else if (fourcc == FOURCC_moof) {
7156           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7157             guint64 dist = 0;
7158             GstClockTime prev_pts;
7159             guint64 prev_offset;
7160             guint64 adapter_discont_offset, adapter_discont_dist;
7161
7162             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7163
7164             /*
7165              * The timestamp of the moof buffer is relevant as some scenarios
7166              * won't have the initial timestamp in the atoms. Whenever a new
7167              * buffer has started, we get that buffer's PTS and use it as a base
7168              * timestamp for the trun entries.
7169              *
7170              * To keep track of the current buffer timestamp and starting point
7171              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7172              * from the beggining of the buffer, with the distance and demux->offset
7173              * we know if it is still the same buffer or not.
7174              */
7175             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7176             prev_offset = demux->offset - dist;
7177             if (demux->fragment_start_offset == -1
7178                 || prev_offset > demux->fragment_start_offset) {
7179               demux->fragment_start_offset = prev_offset;
7180               demux->fragment_start = prev_pts;
7181               GST_DEBUG_OBJECT (demux,
7182                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7183                   GST_TIME_FORMAT, demux->fragment_start_offset,
7184                   GST_TIME_ARGS (demux->fragment_start));
7185             }
7186
7187             /* We can't use prev_offset() here because this would require
7188              * upstream to set consistent and correct offsets on all buffers
7189              * since the discont. Nothing ever did that in the past and we
7190              * would break backwards compatibility here then.
7191              * Instead take the offset we had at the last discont and count
7192              * the bytes from there. This works with old code as there would
7193              * be no discont between moov and moof, and also works with
7194              * adaptivedemux which correctly sets offset and will set the
7195              * DISCONT flag accordingly when needed.
7196              *
7197              * We also only do this for upstream TIME segments as otherwise
7198              * there are potential backwards compatibility problems with
7199              * seeking in PUSH mode and upstream providing inconsistent
7200              * timestamps. */
7201             adapter_discont_offset =
7202                 gst_adapter_offset_at_discont (demux->adapter);
7203             adapter_discont_dist =
7204                 gst_adapter_distance_from_discont (demux->adapter);
7205
7206             GST_DEBUG_OBJECT (demux,
7207                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7208                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7209                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7210
7211             if (demux->upstream_format_is_time) {
7212               demux->moof_offset = adapter_discont_offset;
7213               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7214                 demux->moof_offset += adapter_discont_dist;
7215               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7216                 demux->moof_offset = demux->offset;
7217             } else {
7218               demux->moof_offset = demux->offset;
7219             }
7220
7221             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7222                     demux->moof_offset, NULL)) {
7223               gst_adapter_unmap (demux->adapter);
7224               ret = GST_FLOW_ERROR;
7225               goto done;
7226             }
7227             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7228             if (demux->mss_mode && !demux->exposed) {
7229               if (!demux->pending_newsegment) {
7230                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
7231                 demux->pending_newsegment =
7232                     gst_event_new_segment (&demux->segment);
7233                 if (demux->segment_seqnum)
7234                   gst_event_set_seqnum (demux->pending_newsegment,
7235                       demux->segment_seqnum);
7236               }
7237               qtdemux_expose_streams (demux);
7238             }
7239           } else {
7240             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7241           }
7242         } else if (fourcc == FOURCC_ftyp) {
7243           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7244           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7245         } else if (fourcc == FOURCC_uuid) {
7246           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7247           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7248         } else if (fourcc == FOURCC_sidx) {
7249           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7250           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7251         } else {
7252           switch (fourcc) {
7253             case FOURCC_styp:
7254               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7255                * FALLTHROUGH */
7256             case FOURCC_free:
7257               /* [free] is a padding atom */
7258               GST_DEBUG_OBJECT (demux,
7259                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7260                   GST_FOURCC_ARGS (fourcc));
7261               break;
7262             default:
7263               GST_WARNING_OBJECT (demux,
7264                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7265                   GST_FOURCC_ARGS (fourcc));
7266               /* Let's jump that one and go back to initial state */
7267               break;
7268           }
7269         }
7270         gst_adapter_unmap (demux->adapter);
7271         data = NULL;
7272
7273         if (demux->mdatbuffer && demux->n_streams) {
7274           gsize remaining_data_size = 0;
7275
7276           /* the mdat was before the header */
7277           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7278               demux->n_streams, demux->mdatbuffer);
7279           /* restore our adapter/offset view of things with upstream;
7280            * put preceding buffered data ahead of current moov data.
7281            * This should also handle evil mdat, moov, mdat cases and alike */
7282           gst_adapter_flush (demux->adapter, demux->neededbytes);
7283
7284           /* Store any remaining data after the mdat for later usage */
7285           remaining_data_size = gst_adapter_available (demux->adapter);
7286           if (remaining_data_size > 0) {
7287             g_assert (demux->restoredata_buffer == NULL);
7288             demux->restoredata_buffer =
7289                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7290             demux->restoredata_offset = demux->offset + demux->neededbytes;
7291             GST_DEBUG_OBJECT (demux,
7292                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7293                 G_GUINT64_FORMAT, remaining_data_size,
7294                 demux->restoredata_offset);
7295           }
7296
7297           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7298           demux->mdatbuffer = NULL;
7299           demux->offset = demux->mdatoffset;
7300           demux->neededbytes = next_entry_size (demux);
7301           demux->state = QTDEMUX_STATE_MOVIE;
7302           demux->mdatleft = gst_adapter_available (demux->adapter);
7303           demux->mdatsize = demux->mdatleft;
7304         } else {
7305           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7306           gst_adapter_flush (demux->adapter, demux->neededbytes);
7307
7308           /* only go back to the mdat if there are samples to play */
7309           if (demux->got_moov && demux->first_mdat != -1
7310               && has_next_entry (demux)) {
7311             gboolean res;
7312
7313             /* we need to seek back */
7314             res = qtdemux_seek_offset (demux, demux->first_mdat);
7315             if (res) {
7316               demux->offset = demux->first_mdat;
7317             } else {
7318               GST_DEBUG_OBJECT (demux, "Seek back failed");
7319             }
7320           } else {
7321             demux->offset += demux->neededbytes;
7322           }
7323           demux->neededbytes = 16;
7324           demux->state = QTDEMUX_STATE_INITIAL;
7325         }
7326
7327         break;
7328       }
7329       case QTDEMUX_STATE_BUFFER_MDAT:{
7330         GstBuffer *buf;
7331         guint8 fourcc[4];
7332
7333         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7334             demux->offset);
7335         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7336         gst_buffer_extract (buf, 0, fourcc, 4);
7337         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7338             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7339         if (demux->mdatbuffer)
7340           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7341         else
7342           demux->mdatbuffer = buf;
7343         demux->offset += demux->neededbytes;
7344         demux->neededbytes = 16;
7345         demux->state = QTDEMUX_STATE_INITIAL;
7346         gst_qtdemux_post_progress (demux, 1, 1);
7347
7348         break;
7349       }
7350       case QTDEMUX_STATE_MOVIE:{
7351         QtDemuxStream *stream = NULL;
7352         QtDemuxSample *sample;
7353         int i = -1;
7354         GstClockTime dts, pts, duration;
7355         gboolean keyframe;
7356
7357         GST_DEBUG_OBJECT (demux,
7358             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7359
7360         if (demux->fragmented) {
7361           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7362               demux->mdatleft);
7363           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7364             /* if needed data starts within this atom,
7365              * then it should not exceed this atom */
7366             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7367               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7368                   (_("This file is invalid and cannot be played.")),
7369                   ("sample data crosses atom boundary"));
7370               ret = GST_FLOW_ERROR;
7371               break;
7372             }
7373             demux->mdatleft -= demux->neededbytes;
7374           } else {
7375             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7376             /* so we are dropping more than left in this atom */
7377             gst_qtdemux_drop_data (demux, demux->mdatleft);
7378             demux->mdatleft = 0;
7379
7380             /* need to resume atom parsing so we do not miss any other pieces */
7381             demux->state = QTDEMUX_STATE_INITIAL;
7382             demux->neededbytes = 16;
7383
7384             /* check if there was any stored post mdat data from previous buffers */
7385             if (demux->restoredata_buffer) {
7386               g_assert (gst_adapter_available (demux->adapter) == 0);
7387
7388               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7389               demux->restoredata_buffer = NULL;
7390               demux->offset = demux->restoredata_offset;
7391             }
7392
7393             break;
7394           }
7395         }
7396
7397         if (demux->todrop) {
7398           if (demux->cenc_aux_info_offset > 0) {
7399             GstByteReader br;
7400             const guint8 *data;
7401
7402             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7403             data = gst_adapter_map (demux->adapter, demux->todrop);
7404             gst_byte_reader_init (&br, data + 8, demux->todrop);
7405             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
7406                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7407               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7408               ret = GST_FLOW_ERROR;
7409               gst_adapter_unmap (demux->adapter);
7410               g_free (demux->cenc_aux_info_sizes);
7411               demux->cenc_aux_info_sizes = NULL;
7412               goto done;
7413             }
7414             demux->cenc_aux_info_offset = 0;
7415             g_free (demux->cenc_aux_info_sizes);
7416             demux->cenc_aux_info_sizes = NULL;
7417             gst_adapter_unmap (demux->adapter);
7418           }
7419           gst_qtdemux_drop_data (demux, demux->todrop);
7420         }
7421
7422         /* first buffer? */
7423         /* initial newsegment sent here after having added pads,
7424          * possible others in sink_event */
7425         gst_qtdemux_check_send_pending_segment (demux);
7426
7427         /* Figure out which stream this packet belongs to */
7428         for (i = 0; i < demux->n_streams; i++) {
7429           stream = demux->streams[i];
7430           if (stream->sample_index >= stream->n_samples)
7431             continue;
7432           GST_LOG_OBJECT (demux,
7433               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
7434               " / size:%d)", i, stream->sample_index,
7435               stream->samples[stream->sample_index].offset,
7436               stream->samples[stream->sample_index].size);
7437
7438           if (stream->samples[stream->sample_index].offset == demux->offset)
7439             break;
7440         }
7441
7442         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
7443           goto unknown_stream;
7444
7445         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7446
7447         if (stream->new_caps) {
7448           gst_qtdemux_configure_stream (demux, stream);
7449         }
7450
7451         /* Put data in a buffer, set timestamps, caps, ... */
7452         sample = &stream->samples[stream->sample_index];
7453
7454         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7455           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7456               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7457
7458           dts = QTSAMPLE_DTS (stream, sample);
7459           pts = QTSAMPLE_PTS (stream, sample);
7460           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7461           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7462
7463           /* check for segment end */
7464           if (G_UNLIKELY (demux->segment.stop != -1
7465                   && demux->segment.stop <= pts && stream->on_keyframe)) {
7466             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7467             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7468
7469             /* skip this data, stream is EOS */
7470             gst_adapter_flush (demux->adapter, demux->neededbytes);
7471             demux->offset += demux->neededbytes;
7472
7473             /* check if all streams are eos */
7474             ret = GST_FLOW_EOS;
7475             for (i = 0; i < demux->n_streams; i++) {
7476               if (!STREAM_IS_EOS (demux->streams[i])) {
7477                 ret = GST_FLOW_OK;
7478                 break;
7479               }
7480             }
7481           } else {
7482             GstBuffer *outbuf;
7483
7484             outbuf =
7485                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7486
7487             /* FIXME: should either be an assert or a plain check */
7488             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7489
7490             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7491                 dts, pts, duration, keyframe, dts, demux->offset);
7492           }
7493
7494           /* combine flows */
7495           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7496         } else {
7497           /* skip this data, stream is EOS */
7498           gst_adapter_flush (demux->adapter, demux->neededbytes);
7499         }
7500
7501         stream->sample_index++;
7502         stream->offset_in_sample = 0;
7503
7504         /* update current offset and figure out size of next buffer */
7505         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7506             demux->offset, demux->neededbytes);
7507         demux->offset += demux->neededbytes;
7508         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7509             demux->offset);
7510
7511
7512         if (ret == GST_FLOW_EOS) {
7513           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7514           demux->neededbytes = -1;
7515           goto eos;
7516         }
7517
7518         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7519           if (demux->fragmented) {
7520             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7521             /* there may be more to follow, only finish this atom */
7522             demux->todrop = demux->mdatleft;
7523             demux->neededbytes = demux->todrop;
7524             break;
7525           }
7526           goto eos;
7527         }
7528         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7529           goto non_ok_unlinked_flow;
7530         }
7531         break;
7532       }
7533       default:
7534         goto invalid_state;
7535     }
7536   }
7537
7538   /* when buffering movie data, at least show user something is happening */
7539   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7540       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7541     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7542         demux->neededbytes);
7543   }
7544 done:
7545
7546   return ret;
7547
7548   /* ERRORS */
7549 non_ok_unlinked_flow:
7550   {
7551     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7552         gst_flow_get_name (ret));
7553     return ret;
7554   }
7555 unknown_stream:
7556   {
7557     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7558     ret = GST_FLOW_ERROR;
7559     goto done;
7560   }
7561 eos:
7562   {
7563     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7564     ret = GST_FLOW_EOS;
7565     goto done;
7566   }
7567 invalid_state:
7568   {
7569     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7570         (NULL), ("qtdemuxer invalid state %d", demux->state));
7571     ret = GST_FLOW_ERROR;
7572     goto done;
7573   }
7574 no_moov:
7575   {
7576     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7577         (NULL), ("no 'moov' atom within the first 10 MB"));
7578     ret = GST_FLOW_ERROR;
7579     goto done;
7580   }
7581 }
7582
7583 static gboolean
7584 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7585 {
7586   GstQuery *query;
7587   gboolean pull_mode;
7588
7589   query = gst_query_new_scheduling ();
7590
7591   if (!gst_pad_peer_query (sinkpad, query)) {
7592     gst_query_unref (query);
7593     goto activate_push;
7594   }
7595
7596   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7597       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7598   gst_query_unref (query);
7599
7600   if (!pull_mode)
7601     goto activate_push;
7602
7603   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7604   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7605
7606 activate_push:
7607   {
7608     GST_DEBUG_OBJECT (sinkpad, "activating push");
7609     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7610   }
7611 }
7612
7613 static gboolean
7614 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7615     GstPadMode mode, gboolean active)
7616 {
7617   gboolean res;
7618   GstQTDemux *demux = GST_QTDEMUX (parent);
7619
7620   switch (mode) {
7621     case GST_PAD_MODE_PUSH:
7622       demux->pullbased = FALSE;
7623       res = TRUE;
7624       break;
7625     case GST_PAD_MODE_PULL:
7626       if (active) {
7627         demux->pullbased = TRUE;
7628         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7629             sinkpad, NULL);
7630       } else {
7631         res = gst_pad_stop_task (sinkpad);
7632       }
7633       break;
7634     default:
7635       res = FALSE;
7636       break;
7637   }
7638   return res;
7639 }
7640
7641 #ifdef HAVE_ZLIB
7642 static void *
7643 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7644 {
7645   guint8 *buffer;
7646   z_stream z;
7647   int ret;
7648
7649   memset (&z, 0, sizeof (z));
7650   z.zalloc = NULL;
7651   z.zfree = NULL;
7652   z.opaque = NULL;
7653
7654   if ((ret = inflateInit (&z)) != Z_OK) {
7655     GST_ERROR ("inflateInit() returned %d", ret);
7656     return NULL;
7657   }
7658
7659   z.next_in = z_buffer;
7660   z.avail_in = z_length;
7661
7662   buffer = (guint8 *) g_malloc (*length);
7663   z.avail_out = *length;
7664   z.next_out = (Bytef *) buffer;
7665   do {
7666     ret = inflate (&z, Z_NO_FLUSH);
7667     if (ret == Z_STREAM_END) {
7668       break;
7669     } else if (ret != Z_OK) {
7670       GST_WARNING ("inflate() returned %d", ret);
7671       break;
7672     }
7673
7674     *length += 4096;
7675     buffer = (guint8 *) g_realloc (buffer, *length);
7676     z.next_out = (Bytef *) (buffer + z.total_out);
7677     z.avail_out += 4096;
7678   } while (z.avail_in > 0);
7679
7680   if (ret != Z_STREAM_END) {
7681     g_free (buffer);
7682     buffer = NULL;
7683     *length = 0;
7684   } else {
7685     *length = z.total_out;
7686   }
7687
7688   inflateEnd (&z);
7689
7690   return buffer;
7691 }
7692 #endif /* HAVE_ZLIB */
7693
7694 static gboolean
7695 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7696 {
7697   GNode *cmov;
7698
7699   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7700
7701   /* counts as header data */
7702   qtdemux->header_size += length;
7703
7704   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7705   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7706
7707   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7708   if (cmov) {
7709     guint32 method;
7710     GNode *dcom;
7711     GNode *cmvd;
7712     guint32 dcom_len;
7713
7714     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7715     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7716     if (dcom == NULL || cmvd == NULL)
7717       goto invalid_compression;
7718
7719     dcom_len = QT_UINT32 (dcom->data);
7720     if (dcom_len < 12)
7721       goto invalid_compression;
7722
7723     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7724     switch (method) {
7725 #ifdef HAVE_ZLIB
7726       case FOURCC_zlib:{
7727         guint uncompressed_length;
7728         guint compressed_length;
7729         guint8 *buf;
7730         guint32 cmvd_len;
7731
7732         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7733         if (cmvd_len < 12)
7734           goto invalid_compression;
7735
7736         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7737         compressed_length = cmvd_len - 12;
7738         GST_LOG ("length = %u", uncompressed_length);
7739
7740         buf =
7741             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7742             compressed_length, &uncompressed_length);
7743
7744         if (buf) {
7745           qtdemux->moov_node_compressed = qtdemux->moov_node;
7746           qtdemux->moov_node = g_node_new (buf);
7747
7748           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7749               uncompressed_length);
7750         }
7751         break;
7752       }
7753 #endif /* HAVE_ZLIB */
7754       default:
7755         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7756             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7757         break;
7758     }
7759   }
7760   return TRUE;
7761
7762   /* ERRORS */
7763 invalid_compression:
7764   {
7765     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7766     return FALSE;
7767   }
7768 }
7769
7770 static gboolean
7771 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7772     const guint8 * end)
7773 {
7774   while (G_UNLIKELY (buf < end)) {
7775     GNode *child;
7776     guint32 len;
7777
7778     if (G_UNLIKELY (buf + 4 > end)) {
7779       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7780       break;
7781     }
7782     len = QT_UINT32 (buf);
7783     if (G_UNLIKELY (len == 0)) {
7784       GST_LOG_OBJECT (qtdemux, "empty container");
7785       break;
7786     }
7787     if (G_UNLIKELY (len < 8)) {
7788       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7789       break;
7790     }
7791     if (G_UNLIKELY (len > (end - buf))) {
7792       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7793           (gint) (end - buf));
7794       break;
7795     }
7796
7797     child = g_node_new ((guint8 *) buf);
7798     g_node_append (node, child);
7799     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7800     qtdemux_parse_node (qtdemux, child, buf, len);
7801
7802     buf += len;
7803   }
7804   return TRUE;
7805 }
7806
7807 static gboolean
7808 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7809     GNode * xdxt)
7810 {
7811   int len = QT_UINT32 (xdxt->data);
7812   guint8 *buf = xdxt->data;
7813   guint8 *end = buf + len;
7814   GstBuffer *buffer;
7815
7816   /* skip size and type */
7817   buf += 8;
7818   end -= 8;
7819
7820   while (buf < end) {
7821     gint size;
7822     guint32 type;
7823
7824     size = QT_UINT32 (buf);
7825     type = QT_FOURCC (buf + 4);
7826
7827     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7828
7829     if (buf + size > end || size <= 0)
7830       break;
7831
7832     buf += 8;
7833     size -= 8;
7834
7835     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7836         GST_FOURCC_ARGS (type));
7837
7838     switch (type) {
7839       case FOURCC_tCtH:
7840         buffer = gst_buffer_new_and_alloc (size);
7841         gst_buffer_fill (buffer, 0, buf, size);
7842         stream->buffers = g_slist_append (stream->buffers, buffer);
7843         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7844         break;
7845       case FOURCC_tCt_:
7846         buffer = gst_buffer_new_and_alloc (size);
7847         gst_buffer_fill (buffer, 0, buf, size);
7848         stream->buffers = g_slist_append (stream->buffers, buffer);
7849         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7850         break;
7851       case FOURCC_tCtC:
7852         buffer = gst_buffer_new_and_alloc (size);
7853         gst_buffer_fill (buffer, 0, buf, size);
7854         stream->buffers = g_slist_append (stream->buffers, buffer);
7855         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7856         break;
7857       default:
7858         GST_WARNING_OBJECT (qtdemux,
7859             "unknown theora cookie %" GST_FOURCC_FORMAT,
7860             GST_FOURCC_ARGS (type));
7861         break;
7862     }
7863     buf += size;
7864   }
7865   return TRUE;
7866 }
7867
7868 static gboolean
7869 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7870     guint length)
7871 {
7872   guint32 fourcc = 0;
7873   guint32 node_length = 0;
7874   const QtNodeType *type;
7875   const guint8 *end;
7876
7877   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7878
7879   if (G_UNLIKELY (length < 8))
7880     goto not_enough_data;
7881
7882   node_length = QT_UINT32 (buffer);
7883   fourcc = QT_FOURCC (buffer + 4);
7884
7885   /* ignore empty nodes */
7886   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7887     return TRUE;
7888
7889   type = qtdemux_type_get (fourcc);
7890
7891   end = buffer + length;
7892
7893   GST_LOG_OBJECT (qtdemux,
7894       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7895       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7896
7897   if (node_length > length)
7898     goto broken_atom_size;
7899
7900   if (type->flags & QT_FLAG_CONTAINER) {
7901     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7902   } else {
7903     switch (fourcc) {
7904       case FOURCC_stsd:
7905       {
7906         if (node_length < 20) {
7907           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7908           break;
7909         }
7910         GST_DEBUG_OBJECT (qtdemux,
7911             "parsing stsd (sample table, sample description) atom");
7912         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7913         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7914         break;
7915       }
7916       case FOURCC_mp4a:
7917       case FOURCC_alac:
7918       case FOURCC_fLaC:
7919       {
7920         guint32 version;
7921         guint32 offset;
7922         guint min_size;
7923
7924         /* also read alac (or whatever) in stead of mp4a in the following,
7925          * since a similar layout is used in other cases as well */
7926         if (fourcc == FOURCC_mp4a)
7927           min_size = 20;
7928         else if (fourcc == FOURCC_fLaC)
7929           min_size = 86;
7930         else
7931           min_size = 40;
7932
7933         /* There are two things we might encounter here: a true mp4a atom, and
7934            an mp4a entry in an stsd atom. The latter is what we're interested
7935            in, and it looks like an atom, but isn't really one. The true mp4a
7936            atom is short, so we detect it based on length here. */
7937         if (length < min_size) {
7938           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7939               GST_FOURCC_ARGS (fourcc));
7940           break;
7941         }
7942
7943         /* 'version' here is the sound sample description version. Types 0 and
7944            1 are documented in the QTFF reference, but type 2 is not: it's
7945            described in Apple header files instead (struct SoundDescriptionV2
7946            in Movies.h) */
7947         version = QT_UINT16 (buffer + 16);
7948
7949         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7950             GST_FOURCC_ARGS (fourcc), version);
7951
7952         /* parse any esds descriptors */
7953         switch (version) {
7954           case 0:
7955             offset = 0x24;
7956             break;
7957           case 1:
7958             offset = 0x34;
7959             break;
7960           case 2:
7961             offset = 0x48;
7962             break;
7963           default:
7964             GST_WARNING_OBJECT (qtdemux,
7965                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7966                 GST_FOURCC_ARGS (fourcc), version);
7967             offset = 0;
7968             break;
7969         }
7970         if (offset)
7971           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7972         break;
7973       }
7974       case FOURCC_mp4v:
7975       case FOURCC_MP4V:
7976       case FOURCC_fmp4:
7977       case FOURCC_FMP4:
7978       case FOURCC_apcs:
7979       case FOURCC_apch:
7980       case FOURCC_apcn:
7981       case FOURCC_apco:
7982       case FOURCC_ap4h:
7983       case FOURCC_xvid:
7984       case FOURCC_XVID:
7985       case FOURCC_H264:
7986       case FOURCC_avc1:
7987       case FOURCC_avc3:
7988       case FOURCC_H265:
7989       case FOURCC_hvc1:
7990       case FOURCC_hev1:
7991       case FOURCC_mjp2:
7992       case FOURCC_encv:
7993       {
7994         guint32 version;
7995         guint32 str_len;
7996
7997         /* codec_data is contained inside these atoms, which all have
7998          * the same format. */
7999         /* video sample description size is 86 bytes without extension.
8000          * node_length have to be bigger than 86 bytes because video sample
8001          * description can include extenstions such as esds, fiel, glbl, etc. */
8002         if (node_length < 86) {
8003           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8004               " sample description length too short (%u < 86)",
8005               GST_FOURCC_ARGS (fourcc), node_length);
8006           break;
8007         }
8008
8009         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8010             GST_FOURCC_ARGS (fourcc));
8011
8012         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8013          *              its data format.
8014          * revision level (2 bytes) : must be set to 0. */
8015         version = QT_UINT32 (buffer + 16);
8016         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8017
8018         /* compressor name : PASCAL string and informative purposes
8019          * first byte : the number of bytes to be displayed.
8020          *              it has to be less than 32 because it is reserved
8021          *              space of 32 bytes total including itself. */
8022         str_len = QT_UINT8 (buffer + 50);
8023         if (str_len < 32)
8024           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8025               (char *) buffer + 51);
8026         else
8027           GST_WARNING_OBJECT (qtdemux,
8028               "compressorname length too big (%u > 31)", str_len);
8029
8030         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8031             end - buffer);
8032         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8033         break;
8034       }
8035       case FOURCC_meta:
8036       {
8037         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8038         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8039         break;
8040       }
8041       case FOURCC_mp4s:
8042       {
8043         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8044         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8045         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8046         break;
8047       }
8048       case FOURCC_XiTh:
8049       {
8050         guint32 version;
8051         guint32 offset;
8052
8053         if (length < 16) {
8054           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8055               GST_FOURCC_ARGS (fourcc));
8056           break;
8057         }
8058
8059         version = QT_UINT32 (buffer + 12);
8060         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8061
8062         switch (version) {
8063           case 0x00000001:
8064             offset = 0x62;
8065             break;
8066           default:
8067             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8068             offset = 0;
8069             break;
8070         }
8071         if (offset) {
8072           if (length < offset) {
8073             GST_WARNING_OBJECT (qtdemux,
8074                 "skipping too small %" GST_FOURCC_FORMAT " box",
8075                 GST_FOURCC_ARGS (fourcc));
8076             break;
8077           }
8078           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8079         }
8080         break;
8081       }
8082       case FOURCC_in24:
8083       {
8084         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8085         break;
8086       }
8087       case FOURCC_uuid:
8088       {
8089         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8090         break;
8091       }
8092       case FOURCC_enca:
8093       {
8094         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8095         break;
8096       }
8097 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
8098       case FOURCC_SA3D:
8099       {
8100         qtdemux_parse_SA3D (qtdemux, buffer, end - buffer);
8101         break;
8102       }
8103 #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
8104       default:
8105         if (!strcmp (type->name, "unknown"))
8106           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8107         break;
8108     }
8109   }
8110   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8111       GST_FOURCC_ARGS (fourcc));
8112   return TRUE;
8113
8114 /* ERRORS */
8115 not_enough_data:
8116   {
8117     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8118         (_("This file is corrupt and cannot be played.")),
8119         ("Not enough data for an atom header, got only %u bytes", length));
8120     return FALSE;
8121   }
8122 broken_atom_size:
8123   {
8124     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8125         (_("This file is corrupt and cannot be played.")),
8126         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8127             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8128             length));
8129     return FALSE;
8130   }
8131 }
8132
8133 static GNode *
8134 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
8135 {
8136   GNode *child;
8137   guint8 *buffer;
8138   guint32 child_fourcc;
8139
8140   for (child = g_node_first_child (node); child;
8141       child = g_node_next_sibling (child)) {
8142     buffer = (guint8 *) child->data;
8143
8144     child_fourcc = QT_FOURCC (buffer + 4);
8145
8146     if (G_UNLIKELY (child_fourcc == fourcc)) {
8147       return child;
8148     }
8149   }
8150   return NULL;
8151 }
8152
8153 static GNode *
8154 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
8155     GstByteReader * parser)
8156 {
8157   GNode *child;
8158   guint8 *buffer;
8159   guint32 child_fourcc, child_len;
8160
8161   for (child = g_node_first_child (node); child;
8162       child = g_node_next_sibling (child)) {
8163     buffer = (guint8 *) child->data;
8164
8165     child_len = QT_UINT32 (buffer);
8166     child_fourcc = QT_FOURCC (buffer + 4);
8167
8168     if (G_UNLIKELY (child_fourcc == fourcc)) {
8169       if (G_UNLIKELY (child_len < (4 + 4)))
8170         return NULL;
8171       /* FIXME: must verify if atom length < parent atom length */
8172       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8173       return child;
8174     }
8175   }
8176   return NULL;
8177 }
8178
8179 static GNode *
8180 qtdemux_tree_get_child_by_index (GNode * node, guint index)
8181 {
8182   return g_node_nth_child (node, index);
8183 }
8184
8185 static GNode *
8186 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
8187     GstByteReader * parser)
8188 {
8189   GNode *child;
8190   guint8 *buffer;
8191   guint32 child_fourcc, child_len;
8192
8193   for (child = g_node_next_sibling (node); child;
8194       child = g_node_next_sibling (child)) {
8195     buffer = (guint8 *) child->data;
8196
8197     child_fourcc = QT_FOURCC (buffer + 4);
8198
8199     if (child_fourcc == fourcc) {
8200       if (parser) {
8201         child_len = QT_UINT32 (buffer);
8202         if (G_UNLIKELY (child_len < (4 + 4)))
8203           return NULL;
8204         /* FIXME: must verify if atom length < parent atom length */
8205         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8206       }
8207       return child;
8208     }
8209   }
8210   return NULL;
8211 }
8212
8213 static GNode *
8214 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8215 {
8216   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8217 }
8218
8219 static void
8220 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
8221 {
8222 /* FIXME: This can only reliably work if demuxers have a
8223  * separate streaming thread per srcpad. This should be
8224  * done in a demuxer base class, which integrates parts
8225  * of multiqueue
8226  *
8227  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8228  */
8229 #if 0
8230   GstQuery *query;
8231
8232   query = gst_query_new_allocation (stream->caps, FALSE);
8233
8234   if (!gst_pad_peer_query (stream->pad, query)) {
8235     /* not a problem, just debug a little */
8236     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8237   }
8238
8239   if (stream->allocator)
8240     gst_object_unref (stream->allocator);
8241
8242   if (gst_query_get_n_allocation_params (query) > 0) {
8243     /* try the allocator */
8244     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8245         &stream->params);
8246     stream->use_allocator = TRUE;
8247   } else {
8248     stream->allocator = NULL;
8249     gst_allocation_params_init (&stream->params);
8250     stream->use_allocator = FALSE;
8251   }
8252   gst_query_unref (query);
8253 #endif
8254 }
8255
8256 static gboolean
8257 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8258     QtDemuxStream * stream)
8259 {
8260   GstStructure *s;
8261   const gchar *selected_system;
8262
8263   g_return_val_if_fail (qtdemux != NULL, FALSE);
8264   g_return_val_if_fail (stream != NULL, FALSE);
8265   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8266       FALSE);
8267
8268   if (stream->protection_scheme_type != FOURCC_cenc) {
8269     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
8270     return FALSE;
8271   }
8272   if (qtdemux->protection_system_ids == NULL) {
8273     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8274         "cenc protection system information has been found");
8275     return FALSE;
8276   }
8277   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8278   selected_system = gst_protection_select_system ((const gchar **)
8279       qtdemux->protection_system_ids->pdata);
8280   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8281       qtdemux->protection_system_ids->len - 1);
8282   if (!selected_system) {
8283     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8284         "suitable decryptor element has been found");
8285     return FALSE;
8286   }
8287
8288   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8289   if (!gst_structure_has_name (s, "application/x-cenc")) {
8290     gst_structure_set (s,
8291         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8292         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8293         NULL);
8294     gst_structure_set_name (s, "application/x-cenc");
8295   }
8296   return TRUE;
8297 }
8298
8299 static gboolean
8300 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8301 {
8302   if (stream->subtype == FOURCC_vide) {
8303     /* fps is calculated base on the duration of the average framerate since
8304      * qt does not have a fixed framerate. */
8305     gboolean fps_available = TRUE;
8306
8307     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
8308       /* still frame */
8309       CUR_STREAM (stream)->fps_n = 0;
8310       CUR_STREAM (stream)->fps_d = 1;
8311     } else {
8312       if (stream->duration == 0 || stream->n_samples < 2) {
8313         CUR_STREAM (stream)->fps_n = stream->timescale;
8314         CUR_STREAM (stream)->fps_d = 1;
8315         fps_available = FALSE;
8316       } else {
8317         GstClockTime avg_duration;
8318         guint64 duration;
8319         guint32 n_samples;
8320
8321         /* duration and n_samples can be updated for fragmented format
8322          * so, framerate of fragmented format is calculated using data in a moof */
8323         if (qtdemux->fragmented && stream->n_samples_moof > 0
8324             && stream->duration_moof > 0) {
8325           n_samples = stream->n_samples_moof;
8326           duration = stream->duration_moof;
8327         } else {
8328           n_samples = stream->n_samples;
8329           duration = stream->duration;
8330         }
8331
8332         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8333         /* stream->duration is guint64, timescale, n_samples are guint32 */
8334         avg_duration =
8335             gst_util_uint64_scale_round (duration -
8336             stream->first_duration, GST_SECOND,
8337             (guint64) (stream->timescale) * (n_samples - 1));
8338
8339         GST_LOG_OBJECT (qtdemux,
8340             "Calculating avg sample duration based on stream (or moof) duration %"
8341             G_GUINT64_FORMAT
8342             " minus first sample %u, leaving %d samples gives %"
8343             GST_TIME_FORMAT, duration, stream->first_duration,
8344             n_samples - 1, GST_TIME_ARGS (avg_duration));
8345
8346         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8347             &CUR_STREAM (stream)->fps_d);
8348
8349         GST_DEBUG_OBJECT (qtdemux,
8350             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8351             stream->timescale, CUR_STREAM (stream)->fps_n,
8352             CUR_STREAM (stream)->fps_d);
8353       }
8354     }
8355
8356     if (CUR_STREAM (stream)->caps) {
8357       CUR_STREAM (stream)->caps =
8358           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8359
8360       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8361           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8362           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8363
8364       /* set framerate if calculated framerate is reliable */
8365       if (fps_available) {
8366         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8367             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8368             CUR_STREAM (stream)->fps_d, NULL);
8369       }
8370
8371       /* calculate pixel-aspect-ratio using display width and height */
8372       GST_DEBUG_OBJECT (qtdemux,
8373           "video size %dx%d, target display size %dx%d",
8374           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8375           stream->display_width, stream->display_height);
8376       /* qt file might have pasp atom */
8377       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8378         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8379             CUR_STREAM (stream)->par_h);
8380         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8381             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8382             CUR_STREAM (stream)->par_h, NULL);
8383       } else if (stream->display_width > 0 && stream->display_height > 0
8384           && CUR_STREAM (stream)->width > 0
8385           && CUR_STREAM (stream)->height > 0) {
8386         gint n, d;
8387
8388         /* calculate the pixel aspect ratio using the display and pixel w/h */
8389         n = stream->display_width * CUR_STREAM (stream)->height;
8390         d = stream->display_height * CUR_STREAM (stream)->width;
8391         if (n == d)
8392           n = d = 1;
8393         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8394         CUR_STREAM (stream)->par_w = n;
8395         CUR_STREAM (stream)->par_h = d;
8396         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8397             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8398             CUR_STREAM (stream)->par_h, NULL);
8399       }
8400
8401       if (CUR_STREAM (stream)->interlace_mode > 0) {
8402         if (CUR_STREAM (stream)->interlace_mode == 1) {
8403           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8404               G_TYPE_STRING, "progressive", NULL);
8405         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8406           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8407               G_TYPE_STRING, "interleaved", NULL);
8408           if (CUR_STREAM (stream)->field_order == 9) {
8409             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8410                 G_TYPE_STRING, "top-field-first", NULL);
8411           } else if (CUR_STREAM (stream)->field_order == 14) {
8412             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8413                 G_TYPE_STRING, "bottom-field-first", NULL);
8414           }
8415         }
8416       }
8417
8418       /* Create incomplete colorimetry here if needed */
8419       if (CUR_STREAM (stream)->colorimetry.range ||
8420           CUR_STREAM (stream)->colorimetry.matrix ||
8421           CUR_STREAM (stream)->colorimetry.transfer
8422           || CUR_STREAM (stream)->colorimetry.primaries) {
8423         gchar *colorimetry =
8424             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8425         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8426             G_TYPE_STRING, colorimetry, NULL);
8427         g_free (colorimetry);
8428       }
8429
8430       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8431         guint par_w = 1, par_h = 1;
8432
8433         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8434           par_w = CUR_STREAM (stream)->par_w;
8435           par_h = CUR_STREAM (stream)->par_h;
8436         }
8437
8438         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8439                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8440                 par_h)) {
8441           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8442         }
8443
8444         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8445             "multiview-mode", G_TYPE_STRING,
8446             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8447             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8448             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8449       }
8450     }
8451   }
8452
8453   else if (stream->subtype == FOURCC_soun) {
8454     if (CUR_STREAM (stream)->caps) {
8455       CUR_STREAM (stream)->caps =
8456           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8457       if (CUR_STREAM (stream)->rate > 0)
8458         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8459             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8460       if (CUR_STREAM (stream)->n_channels > 0)
8461         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8462             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8463       if (CUR_STREAM (stream)->n_channels > 2) {
8464         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8465          * correctly; this is just the minimum we can do - assume
8466          * we don't actually have any channel positions. */
8467         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8468             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8469       }
8470     }
8471   }
8472
8473   if (stream->pad) {
8474     GstCaps *prev_caps = NULL;
8475
8476     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8477     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8478     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8479     gst_pad_set_active (stream->pad, TRUE);
8480
8481     gst_pad_use_fixed_caps (stream->pad);
8482
8483     if (stream->protected) {
8484       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8485         GST_ERROR_OBJECT (qtdemux,
8486             "Failed to configure protected stream caps.");
8487         return FALSE;
8488       }
8489     }
8490
8491     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8492         CUR_STREAM (stream)->caps);
8493     if (stream->new_stream) {
8494       gchar *stream_id;
8495       GstEvent *event;
8496       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8497
8498       event =
8499           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8500           0);
8501       if (event) {
8502         gst_event_parse_stream_flags (event, &stream_flags);
8503         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8504           qtdemux->have_group_id = TRUE;
8505         else
8506           qtdemux->have_group_id = FALSE;
8507         gst_event_unref (event);
8508       } else if (!qtdemux->have_group_id) {
8509         qtdemux->have_group_id = TRUE;
8510         qtdemux->group_id = gst_util_group_id_next ();
8511       }
8512
8513       stream->new_stream = FALSE;
8514       stream_id =
8515           gst_pad_create_stream_id_printf (stream->pad,
8516           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
8517       event = gst_event_new_stream_start (stream_id);
8518       if (qtdemux->have_group_id)
8519         gst_event_set_group_id (event, qtdemux->group_id);
8520       if (stream->disabled)
8521         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8522       if (CUR_STREAM (stream)->sparse) {
8523         stream_flags |= GST_STREAM_FLAG_SPARSE;
8524       } else {
8525         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8526       }
8527       gst_event_set_stream_flags (event, stream_flags);
8528       gst_pad_push_event (stream->pad, event);
8529       g_free (stream_id);
8530     }
8531
8532     prev_caps = gst_pad_get_current_caps (stream->pad);
8533
8534     if (CUR_STREAM (stream)->caps) {
8535       if (!prev_caps
8536           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8537         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8538             CUR_STREAM (stream)->caps);
8539         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8540       } else {
8541         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8542       }
8543     } else {
8544       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8545     }
8546
8547     if (prev_caps)
8548       gst_caps_unref (prev_caps);
8549     stream->new_caps = FALSE;
8550   }
8551   return TRUE;
8552 }
8553
8554 static void
8555 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8556     QtDemuxStream * stream)
8557 {
8558   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8559     return;
8560
8561   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8562       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8563   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8564           stream->stsd_entries_length)) {
8565     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8566         (_("This file is invalid and cannot be played.")),
8567         ("New sample description id is out of bounds (%d >= %d)",
8568             stream->stsd_sample_description_id, stream->stsd_entries_length));
8569   } else {
8570     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8571     stream->new_caps = TRUE;
8572   }
8573 }
8574
8575 static gboolean
8576 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8577     QtDemuxStream * stream, GstTagList * list)
8578 {
8579   gboolean ret = TRUE;
8580   /* consistent default for push based mode */
8581   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8582
8583   if (stream->subtype == FOURCC_vide) {
8584     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8585
8586     stream->pad =
8587         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8588     g_free (name);
8589
8590     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8591       gst_object_unref (stream->pad);
8592       stream->pad = NULL;
8593       ret = FALSE;
8594       goto done;
8595     }
8596
8597     qtdemux->n_video_streams++;
8598   } else if (stream->subtype == FOURCC_soun) {
8599     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8600
8601     stream->pad =
8602         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8603     g_free (name);
8604     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8605       gst_object_unref (stream->pad);
8606       stream->pad = NULL;
8607       ret = FALSE;
8608       goto done;
8609     }
8610     qtdemux->n_audio_streams++;
8611   } else if (stream->subtype == FOURCC_strm) {
8612     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8613   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8614       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8615     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8616
8617     stream->pad =
8618         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8619     g_free (name);
8620     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8621       gst_object_unref (stream->pad);
8622       stream->pad = NULL;
8623       ret = FALSE;
8624       goto done;
8625     }
8626     qtdemux->n_sub_streams++;
8627   } else if (CUR_STREAM (stream)->caps) {
8628     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8629
8630     stream->pad =
8631         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8632     g_free (name);
8633     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8634       gst_object_unref (stream->pad);
8635       stream->pad = NULL;
8636       ret = FALSE;
8637       goto done;
8638     }
8639     qtdemux->n_video_streams++;
8640   } else {
8641     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8642     goto done;
8643   }
8644
8645   if (stream->pad) {
8646     GList *l;
8647
8648     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8649         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8650     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8651     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8652
8653     if (stream->stream_tags)
8654       gst_tag_list_unref (stream->stream_tags);
8655     stream->stream_tags = list;
8656     list = NULL;
8657     /* global tags go on each pad anyway */
8658     stream->send_global_tags = TRUE;
8659     /* send upstream GST_EVENT_PROTECTION events that were received before
8660        this source pad was created */
8661     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8662       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8663   }
8664 done:
8665   if (list)
8666     gst_tag_list_unref (list);
8667   return ret;
8668 }
8669
8670 /* find next atom with @fourcc starting at @offset */
8671 static GstFlowReturn
8672 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8673     guint64 * length, guint32 fourcc)
8674 {
8675   GstFlowReturn ret;
8676   guint32 lfourcc;
8677   GstBuffer *buf;
8678
8679   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8680       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8681
8682   while (TRUE) {
8683     GstMapInfo map;
8684
8685     buf = NULL;
8686     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8687     if (G_UNLIKELY (ret != GST_FLOW_OK))
8688       goto locate_failed;
8689     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8690       /* likely EOF */
8691       ret = GST_FLOW_EOS;
8692       gst_buffer_unref (buf);
8693       goto locate_failed;
8694     }
8695     gst_buffer_map (buf, &map, GST_MAP_READ);
8696     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8697     gst_buffer_unmap (buf, &map);
8698     gst_buffer_unref (buf);
8699
8700     if (G_UNLIKELY (*length == 0)) {
8701       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8702       ret = GST_FLOW_ERROR;
8703       goto locate_failed;
8704     }
8705
8706     if (lfourcc == fourcc) {
8707       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8708           *offset);
8709       break;
8710     } else {
8711       GST_LOG_OBJECT (qtdemux,
8712           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8713           GST_FOURCC_ARGS (fourcc), *offset);
8714       *offset += *length;
8715     }
8716   }
8717
8718   return GST_FLOW_OK;
8719
8720 locate_failed:
8721   {
8722     /* might simply have had last one */
8723     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8724     return ret;
8725   }
8726 }
8727
8728 /* should only do something in pull mode */
8729 /* call with OBJECT lock */
8730 static GstFlowReturn
8731 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8732 {
8733   guint64 length, offset;
8734   GstBuffer *buf = NULL;
8735   GstFlowReturn ret = GST_FLOW_OK;
8736   GstFlowReturn res = GST_FLOW_OK;
8737   GstMapInfo map;
8738
8739   offset = qtdemux->moof_offset;
8740   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8741
8742   if (!offset) {
8743     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8744     return GST_FLOW_EOS;
8745   }
8746
8747   /* best not do pull etc with lock held */
8748   GST_OBJECT_UNLOCK (qtdemux);
8749
8750   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8751   if (ret != GST_FLOW_OK)
8752     goto flow_failed;
8753
8754   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8755   if (G_UNLIKELY (ret != GST_FLOW_OK))
8756     goto flow_failed;
8757   gst_buffer_map (buf, &map, GST_MAP_READ);
8758   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8759     gst_buffer_unmap (buf, &map);
8760     gst_buffer_unref (buf);
8761     buf = NULL;
8762     goto parse_failed;
8763   }
8764
8765   gst_buffer_unmap (buf, &map);
8766   gst_buffer_unref (buf);
8767   buf = NULL;
8768
8769   offset += length;
8770   /* look for next moof */
8771   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8772   if (G_UNLIKELY (ret != GST_FLOW_OK))
8773     goto flow_failed;
8774
8775 exit:
8776   GST_OBJECT_LOCK (qtdemux);
8777
8778   qtdemux->moof_offset = offset;
8779
8780   return res;
8781
8782 parse_failed:
8783   {
8784     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8785     offset = 0;
8786     res = GST_FLOW_ERROR;
8787     goto exit;
8788   }
8789 flow_failed:
8790   {
8791     /* maybe upstream temporarily flushing */
8792     if (ret != GST_FLOW_FLUSHING) {
8793       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8794       offset = 0;
8795     } else {
8796       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8797       /* resume at current position next time */
8798     }
8799     res = ret;
8800     goto exit;
8801   }
8802 }
8803
8804 /* initialise bytereaders for stbl sub-atoms */
8805 static gboolean
8806 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8807 {
8808   stream->stbl_index = -1;      /* no samples have yet been parsed */
8809   stream->sample_index = -1;
8810
8811   /* time-to-sample atom */
8812   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8813     goto corrupt_file;
8814
8815   /* copy atom data into a new buffer for later use */
8816   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8817
8818   /* skip version + flags */
8819   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8820       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8821     goto corrupt_file;
8822   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8823
8824   /* make sure there's enough data */
8825   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8826     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8827     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8828         stream->n_sample_times);
8829     if (!stream->n_sample_times)
8830       goto corrupt_file;
8831   }
8832
8833   /* sync sample atom */
8834   stream->stps_present = FALSE;
8835   if ((stream->stss_present =
8836           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8837               &stream->stss) ? TRUE : FALSE) == TRUE) {
8838     /* copy atom data into a new buffer for later use */
8839     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8840
8841     /* skip version + flags */
8842     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8843         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8844       goto corrupt_file;
8845
8846     if (stream->n_sample_syncs) {
8847       /* make sure there's enough data */
8848       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8849         goto corrupt_file;
8850     }
8851
8852     /* partial sync sample atom */
8853     if ((stream->stps_present =
8854             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8855                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8856       /* copy atom data into a new buffer for later use */
8857       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8858
8859       /* skip version + flags */
8860       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8861           !gst_byte_reader_get_uint32_be (&stream->stps,
8862               &stream->n_sample_partial_syncs))
8863         goto corrupt_file;
8864
8865       /* if there are no entries, the stss table contains the real
8866        * sync samples */
8867       if (stream->n_sample_partial_syncs) {
8868         /* make sure there's enough data */
8869         if (!qt_atom_parser_has_chunks (&stream->stps,
8870                 stream->n_sample_partial_syncs, 4))
8871           goto corrupt_file;
8872       }
8873     }
8874   }
8875
8876   /* sample size */
8877   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8878     goto no_samples;
8879
8880   /* copy atom data into a new buffer for later use */
8881   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8882
8883   /* skip version + flags */
8884   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8885       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8886     goto corrupt_file;
8887
8888   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8889     goto corrupt_file;
8890
8891   if (!stream->n_samples)
8892     goto no_samples;
8893
8894   /* sample-to-chunk atom */
8895   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8896     goto corrupt_file;
8897
8898   /* copy atom data into a new buffer for later use */
8899   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8900
8901   /* skip version + flags */
8902   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8903       !gst_byte_reader_get_uint32_be (&stream->stsc,
8904           &stream->n_samples_per_chunk))
8905     goto corrupt_file;
8906
8907   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8908       stream->n_samples_per_chunk);
8909
8910   /* make sure there's enough data */
8911   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8912           12))
8913     goto corrupt_file;
8914
8915
8916   /* chunk offset */
8917   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8918     stream->co_size = sizeof (guint32);
8919   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8920           &stream->stco))
8921     stream->co_size = sizeof (guint64);
8922   else
8923     goto corrupt_file;
8924
8925   /* copy atom data into a new buffer for later use */
8926   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8927
8928   /* skip version + flags */
8929   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8930     goto corrupt_file;
8931
8932   /* chunks_are_samples == TRUE means treat chunks as samples */
8933   stream->chunks_are_samples = stream->sample_size
8934       && !CUR_STREAM (stream)->sampled;
8935   if (stream->chunks_are_samples) {
8936     /* treat chunks as samples */
8937     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8938       goto corrupt_file;
8939   } else {
8940     /* skip number of entries */
8941     if (!gst_byte_reader_skip (&stream->stco, 4))
8942       goto corrupt_file;
8943
8944     /* make sure there are enough data in the stsz atom */
8945     if (!stream->sample_size) {
8946       /* different sizes for each sample */
8947       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8948         goto corrupt_file;
8949     }
8950   }
8951
8952   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8953       stream->n_samples, (guint) sizeof (QtDemuxSample),
8954       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8955
8956   if (stream->n_samples >=
8957       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8958     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8959         "be larger than %uMB (broken file?)", stream->n_samples,
8960         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8961     return FALSE;
8962   }
8963
8964   g_assert (stream->samples == NULL);
8965   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8966   if (!stream->samples) {
8967     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8968         stream->n_samples);
8969     return FALSE;
8970   }
8971
8972   /* composition time-to-sample */
8973   if ((stream->ctts_present =
8974           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8975               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8976     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8977
8978     /* copy atom data into a new buffer for later use */
8979     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8980
8981     /* skip version + flags */
8982     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8983         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8984             &stream->n_composition_times))
8985       goto corrupt_file;
8986
8987     /* make sure there's enough data */
8988     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8989             4 + 4))
8990       goto corrupt_file;
8991
8992     /* This is optional, if missing we iterate the ctts */
8993     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8994       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8995           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8996         g_free ((gpointer) cslg.data);
8997         goto corrupt_file;
8998       }
8999     } else {
9000       gint32 cslg_least = 0;
9001       guint num_entries, pos;
9002       gint i;
9003
9004       pos = gst_byte_reader_get_pos (&stream->ctts);
9005       num_entries = stream->n_composition_times;
9006
9007       stream->cslg_shift = 0;
9008
9009       for (i = 0; i < num_entries; i++) {
9010         gint32 offset;
9011
9012         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9013         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9014
9015         if (offset < cslg_least)
9016           cslg_least = offset;
9017       }
9018
9019       if (cslg_least < 0)
9020         stream->cslg_shift = ABS (cslg_least);
9021       else
9022         stream->cslg_shift = 0;
9023
9024       /* reset the reader so we can generate sample table */
9025       gst_byte_reader_set_pos (&stream->ctts, pos);
9026     }
9027   } else {
9028     /* Ensure the cslg_shift value is consistent so we can use it
9029      * unconditionnally to produce TS and Segment */
9030     stream->cslg_shift = 0;
9031   }
9032
9033   return TRUE;
9034
9035 corrupt_file:
9036   {
9037     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9038         (_("This file is corrupt and cannot be played.")), (NULL));
9039     return FALSE;
9040   }
9041 no_samples:
9042   {
9043     gst_qtdemux_stbl_free (stream);
9044     if (!qtdemux->fragmented) {
9045       /* not quite good */
9046       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9047       return FALSE;
9048     } else {
9049       /* may pick up samples elsewhere */
9050       return TRUE;
9051     }
9052   }
9053 }
9054
9055 /* collect samples from the next sample to be parsed up to sample @n for @stream
9056  * by reading the info from @stbl
9057  *
9058  * This code can be executed from both the streaming thread and the seeking
9059  * thread so it takes the object lock to protect itself
9060  */
9061 static gboolean
9062 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9063 {
9064   gint i, j, k;
9065   QtDemuxSample *samples, *first, *cur, *last;
9066   guint32 n_samples_per_chunk;
9067   guint32 n_samples;
9068
9069   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9070       GST_FOURCC_FORMAT ", pad %s",
9071       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9072       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9073
9074   n_samples = stream->n_samples;
9075
9076   if (n >= n_samples)
9077     goto out_of_samples;
9078
9079   GST_OBJECT_LOCK (qtdemux);
9080   if (n <= stream->stbl_index)
9081     goto already_parsed;
9082
9083   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9084
9085   if (!stream->stsz.data) {
9086     /* so we already parsed and passed all the moov samples;
9087      * onto fragmented ones */
9088     g_assert (qtdemux->fragmented);
9089     goto done;
9090   }
9091
9092   /* pointer to the sample table */
9093   samples = stream->samples;
9094
9095   /* starts from -1, moves to the next sample index to parse */
9096   stream->stbl_index++;
9097
9098   /* keep track of the first and last sample to fill */
9099   first = &samples[stream->stbl_index];
9100   last = &samples[n];
9101
9102   if (!stream->chunks_are_samples) {
9103     /* set the sample sizes */
9104     if (stream->sample_size == 0) {
9105       /* different sizes for each sample */
9106       for (cur = first; cur <= last; cur++) {
9107         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9108         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9109             (guint) (cur - samples), cur->size);
9110       }
9111     } else {
9112       /* samples have the same size */
9113       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9114       for (cur = first; cur <= last; cur++)
9115         cur->size = stream->sample_size;
9116     }
9117   }
9118
9119   n_samples_per_chunk = stream->n_samples_per_chunk;
9120   cur = first;
9121
9122   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9123     guint32 last_chunk;
9124
9125     if (stream->stsc_chunk_index >= stream->last_chunk
9126         || stream->stsc_chunk_index < stream->first_chunk) {
9127       stream->first_chunk =
9128           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9129       stream->samples_per_chunk =
9130           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9131       /* starts from 1 */
9132       stream->stsd_sample_description_id =
9133           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9134
9135       /* chunk numbers are counted from 1 it seems */
9136       if (G_UNLIKELY (stream->first_chunk == 0))
9137         goto corrupt_file;
9138
9139       --stream->first_chunk;
9140
9141       /* the last chunk of each entry is calculated by taking the first chunk
9142        * of the next entry; except if there is no next, where we fake it with
9143        * INT_MAX */
9144       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9145         stream->last_chunk = G_MAXUINT32;
9146       } else {
9147         stream->last_chunk =
9148             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9149         if (G_UNLIKELY (stream->last_chunk == 0))
9150           goto corrupt_file;
9151
9152         --stream->last_chunk;
9153       }
9154
9155       GST_LOG_OBJECT (qtdemux,
9156           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9157           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9158           stream->samples_per_chunk, stream->stsd_sample_description_id);
9159
9160       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9161         goto corrupt_file;
9162
9163       if (stream->last_chunk != G_MAXUINT32) {
9164         if (!qt_atom_parser_peek_sub (&stream->stco,
9165                 stream->first_chunk * stream->co_size,
9166                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9167                 &stream->co_chunk))
9168           goto corrupt_file;
9169
9170       } else {
9171         stream->co_chunk = stream->stco;
9172         if (!gst_byte_reader_skip (&stream->co_chunk,
9173                 stream->first_chunk * stream->co_size))
9174           goto corrupt_file;
9175       }
9176
9177       stream->stsc_chunk_index = stream->first_chunk;
9178     }
9179
9180     last_chunk = stream->last_chunk;
9181
9182     if (stream->chunks_are_samples) {
9183       cur = &samples[stream->stsc_chunk_index];
9184
9185       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9186         if (j > n) {
9187           /* save state */
9188           stream->stsc_chunk_index = j;
9189           goto done;
9190         }
9191
9192         cur->offset =
9193             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9194             stream->co_size);
9195
9196         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9197             "%" G_GUINT64_FORMAT, j, cur->offset);
9198
9199         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9200             CUR_STREAM (stream)->bytes_per_frame > 0) {
9201           cur->size =
9202               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9203               CUR_STREAM (stream)->samples_per_frame *
9204               CUR_STREAM (stream)->bytes_per_frame;
9205         } else {
9206           cur->size = stream->samples_per_chunk;
9207         }
9208
9209         GST_DEBUG_OBJECT (qtdemux,
9210             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9211             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9212                     stream->stco_sample_index)), cur->size);
9213
9214         cur->timestamp = stream->stco_sample_index;
9215         cur->duration = stream->samples_per_chunk;
9216         cur->keyframe = TRUE;
9217         cur++;
9218
9219         stream->stco_sample_index += stream->samples_per_chunk;
9220       }
9221       stream->stsc_chunk_index = j;
9222     } else {
9223       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9224         guint32 samples_per_chunk;
9225         guint64 chunk_offset;
9226
9227         if (!stream->stsc_sample_index
9228             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9229                 &stream->chunk_offset))
9230           goto corrupt_file;
9231
9232         samples_per_chunk = stream->samples_per_chunk;
9233         chunk_offset = stream->chunk_offset;
9234
9235         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9236           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9237               G_GUINT64_FORMAT " and size %d",
9238               (guint) (cur - samples), chunk_offset, cur->size);
9239
9240           cur->offset = chunk_offset;
9241           chunk_offset += cur->size;
9242           cur++;
9243
9244           if (G_UNLIKELY (cur > last)) {
9245             /* save state */
9246             stream->stsc_sample_index = k + 1;
9247             stream->chunk_offset = chunk_offset;
9248             stream->stsc_chunk_index = j;
9249             goto done2;
9250           }
9251         }
9252         stream->stsc_sample_index = 0;
9253       }
9254       stream->stsc_chunk_index = j;
9255     }
9256     stream->stsc_index++;
9257   }
9258
9259   if (stream->chunks_are_samples)
9260     goto ctts;
9261 done2:
9262   {
9263     guint32 n_sample_times;
9264
9265     n_sample_times = stream->n_sample_times;
9266     cur = first;
9267
9268     for (i = stream->stts_index; i < n_sample_times; i++) {
9269       guint32 stts_samples;
9270       gint32 stts_duration;
9271       gint64 stts_time;
9272
9273       if (stream->stts_sample_index >= stream->stts_samples
9274           || !stream->stts_sample_index) {
9275
9276         stream->stts_samples =
9277             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9278         stream->stts_duration =
9279             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9280
9281         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9282             i, stream->stts_samples, stream->stts_duration);
9283
9284         stream->stts_sample_index = 0;
9285       }
9286
9287       stts_samples = stream->stts_samples;
9288       stts_duration = stream->stts_duration;
9289       stts_time = stream->stts_time;
9290
9291       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9292         GST_DEBUG_OBJECT (qtdemux,
9293             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9294             (guint) (cur - samples), j,
9295             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9296
9297         cur->timestamp = stts_time;
9298         cur->duration = stts_duration;
9299
9300         /* avoid 32-bit wrap-around,
9301          * but still mind possible 'negative' duration */
9302         stts_time += (gint64) stts_duration;
9303         cur++;
9304
9305         if (G_UNLIKELY (cur > last)) {
9306           /* save values */
9307           stream->stts_time = stts_time;
9308           stream->stts_sample_index = j + 1;
9309           if (stream->stts_sample_index >= stream->stts_samples)
9310             stream->stts_index++;
9311           goto done3;
9312         }
9313       }
9314       stream->stts_sample_index = 0;
9315       stream->stts_time = stts_time;
9316       stream->stts_index++;
9317     }
9318     /* fill up empty timestamps with the last timestamp, this can happen when
9319      * the last samples do not decode and so we don't have timestamps for them.
9320      * We however look at the last timestamp to estimate the track length so we
9321      * need something in here. */
9322     for (; cur < last; cur++) {
9323       GST_DEBUG_OBJECT (qtdemux,
9324           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9325           (guint) (cur - samples),
9326           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9327       cur->timestamp = stream->stts_time;
9328       cur->duration = -1;
9329     }
9330   }
9331 done3:
9332   {
9333     /* sample sync, can be NULL */
9334     if (stream->stss_present == TRUE) {
9335       guint32 n_sample_syncs;
9336
9337       n_sample_syncs = stream->n_sample_syncs;
9338
9339       if (!n_sample_syncs) {
9340         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9341         stream->all_keyframe = TRUE;
9342       } else {
9343         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9344           /* note that the first sample is index 1, not 0 */
9345           guint32 index;
9346
9347           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9348
9349           if (G_LIKELY (index > 0 && index <= n_samples)) {
9350             index -= 1;
9351             samples[index].keyframe = TRUE;
9352             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9353             /* and exit if we have enough samples */
9354             if (G_UNLIKELY (index >= n)) {
9355               i++;
9356               break;
9357             }
9358           }
9359         }
9360         /* save state */
9361         stream->stss_index = i;
9362       }
9363
9364       /* stps marks partial sync frames like open GOP I-Frames */
9365       if (stream->stps_present == TRUE) {
9366         guint32 n_sample_partial_syncs;
9367
9368         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9369
9370         /* if there are no entries, the stss table contains the real
9371          * sync samples */
9372         if (n_sample_partial_syncs) {
9373           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9374             /* note that the first sample is index 1, not 0 */
9375             guint32 index;
9376
9377             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9378
9379             if (G_LIKELY (index > 0 && index <= n_samples)) {
9380               index -= 1;
9381               samples[index].keyframe = TRUE;
9382               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9383               /* and exit if we have enough samples */
9384               if (G_UNLIKELY (index >= n)) {
9385                 i++;
9386                 break;
9387               }
9388             }
9389           }
9390           /* save state */
9391           stream->stps_index = i;
9392         }
9393       }
9394     } else {
9395       /* no stss, all samples are keyframes */
9396       stream->all_keyframe = TRUE;
9397       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9398     }
9399   }
9400
9401 ctts:
9402   /* composition time to sample */
9403   if (stream->ctts_present == TRUE) {
9404     guint32 n_composition_times;
9405     guint32 ctts_count;
9406     gint32 ctts_soffset;
9407
9408     /* Fill in the pts_offsets */
9409     cur = first;
9410     n_composition_times = stream->n_composition_times;
9411
9412     for (i = stream->ctts_index; i < n_composition_times; i++) {
9413       if (stream->ctts_sample_index >= stream->ctts_count
9414           || !stream->ctts_sample_index) {
9415         stream->ctts_count =
9416             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9417         stream->ctts_soffset =
9418             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9419         stream->ctts_sample_index = 0;
9420       }
9421
9422       ctts_count = stream->ctts_count;
9423       ctts_soffset = stream->ctts_soffset;
9424
9425       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9426         cur->pts_offset = ctts_soffset;
9427         cur++;
9428
9429         if (G_UNLIKELY (cur > last)) {
9430           /* save state */
9431           stream->ctts_sample_index = j + 1;
9432           goto done;
9433         }
9434       }
9435       stream->ctts_sample_index = 0;
9436       stream->ctts_index++;
9437     }
9438   }
9439 done:
9440   stream->stbl_index = n;
9441   /* if index has been completely parsed, free data that is no-longer needed */
9442   if (n + 1 == stream->n_samples) {
9443     gst_qtdemux_stbl_free (stream);
9444     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9445     if (qtdemux->pullbased) {
9446       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9447       while (n + 1 == stream->n_samples)
9448         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9449           break;
9450     }
9451   }
9452   GST_OBJECT_UNLOCK (qtdemux);
9453
9454   return TRUE;
9455
9456   /* SUCCESS */
9457 already_parsed:
9458   {
9459     GST_LOG_OBJECT (qtdemux,
9460         "Tried to parse up to sample %u but this sample has already been parsed",
9461         n);
9462     /* if fragmented, there may be more */
9463     if (qtdemux->fragmented && n == stream->stbl_index)
9464       goto done;
9465     GST_OBJECT_UNLOCK (qtdemux);
9466     return TRUE;
9467   }
9468   /* ERRORS */
9469 out_of_samples:
9470   {
9471     GST_LOG_OBJECT (qtdemux,
9472         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9473         stream->n_samples);
9474     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9475         (_("This file is corrupt and cannot be played.")), (NULL));
9476     return FALSE;
9477   }
9478 corrupt_file:
9479   {
9480     GST_OBJECT_UNLOCK (qtdemux);
9481     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9482         (_("This file is corrupt and cannot be played.")), (NULL));
9483     return FALSE;
9484   }
9485 }
9486
9487 /* collect all segment info for @stream.
9488  */
9489 static gboolean
9490 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9491     GNode * trak)
9492 {
9493   GNode *edts;
9494   /* accept edts if they contain gaps at start and there is only
9495    * one media segment */
9496   gboolean allow_pushbased_edts = TRUE;
9497   gint media_segments_count = 0;
9498
9499   /* parse and prepare segment info from the edit list */
9500   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9501   stream->n_segments = 0;
9502   stream->segments = NULL;
9503   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9504     GNode *elst;
9505     gint n_segments;
9506     gint i, count, entry_size;
9507     guint64 time;
9508     GstClockTime stime;
9509     const guint8 *buffer;
9510     guint8 version;
9511     guint32 size;
9512
9513     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9514     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9515       goto done;
9516
9517     buffer = elst->data;
9518
9519     size = QT_UINT32 (buffer);
9520     /* version, flags, n_segments */
9521     if (size < 16) {
9522       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9523       goto done;
9524     }
9525     version = QT_UINT8 (buffer + 8);
9526     entry_size = (version == 1) ? 20 : 12;
9527
9528     n_segments = QT_UINT32 (buffer + 12);
9529
9530     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9531       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9532       goto done;
9533     }
9534
9535     /* we might allocate a bit too much, at least allocate 1 segment */
9536     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9537
9538     /* segments always start from 0 */
9539     time = 0;
9540     stime = 0;
9541     count = 0;
9542     buffer += 16;
9543     for (i = 0; i < n_segments; i++) {
9544       guint64 duration;
9545       guint64 media_time;
9546       gboolean time_valid = TRUE;
9547       QtDemuxSegment *segment;
9548       guint32 rate_int;
9549       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9550
9551       if (version == 1) {
9552         media_time = QT_UINT64 (buffer + 8);
9553         duration = QT_UINT64 (buffer);
9554         if (media_time == G_MAXUINT64)
9555           time_valid = FALSE;
9556       } else {
9557         media_time = QT_UINT32 (buffer + 4);
9558         duration = QT_UINT32 (buffer);
9559         if (media_time == G_MAXUINT32)
9560           time_valid = FALSE;
9561       }
9562
9563       if (time_valid)
9564         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9565
9566       segment = &stream->segments[count++];
9567
9568       /* time and duration expressed in global timescale */
9569       segment->time = stime;
9570       /* add non scaled values so we don't cause roundoff errors */
9571       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9572         time += duration;
9573         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9574         segment->duration = stime - segment->time;
9575       } else {
9576         /* zero duration does not imply media_start == media_stop
9577          * but, only specify media_start.*/
9578         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9579         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9580             && stime >= media_start) {
9581           segment->duration = stime - media_start;
9582         } else {
9583           segment->duration = GST_CLOCK_TIME_NONE;
9584         }
9585       }
9586       segment->stop_time = stime;
9587
9588       segment->trak_media_start = media_time;
9589       /* media_time expressed in stream timescale */
9590       if (time_valid) {
9591         segment->media_start = media_start;
9592         segment->media_stop = segment->media_start + segment->duration;
9593         media_segments_count++;
9594       } else {
9595         segment->media_start = GST_CLOCK_TIME_NONE;
9596         segment->media_stop = GST_CLOCK_TIME_NONE;
9597       }
9598       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9599
9600       if (rate_int <= 1) {
9601         /* 0 is not allowed, some programs write 1 instead of the floating point
9602          * value */
9603         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9604             rate_int);
9605         segment->rate = 1;
9606       } else {
9607         segment->rate = rate_int / 65536.0;
9608       }
9609
9610       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9611           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9612           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9613           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9614           i, GST_TIME_ARGS (segment->time),
9615           GST_TIME_ARGS (segment->duration),
9616           GST_TIME_ARGS (segment->media_start), media_time,
9617           GST_TIME_ARGS (segment->media_stop),
9618           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9619           stream->timescale);
9620       if (segment->stop_time > qtdemux->segment.stop) {
9621         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9622             " extends to %" GST_TIME_FORMAT
9623             " past the end of the file duration %" GST_TIME_FORMAT
9624             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9625             GST_TIME_ARGS (qtdemux->segment.stop));
9626         qtdemux->segment.stop = segment->stop_time;
9627       }
9628
9629       buffer += entry_size;
9630     }
9631     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9632     stream->n_segments = count;
9633     if (media_segments_count != 1)
9634       allow_pushbased_edts = FALSE;
9635   }
9636 done:
9637
9638   /* push based does not handle segments, so act accordingly here,
9639    * and warn if applicable */
9640   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9641     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9642     /* remove and use default one below, we stream like it anyway */
9643     g_free (stream->segments);
9644     stream->segments = NULL;
9645     stream->n_segments = 0;
9646   }
9647
9648   /* no segments, create one to play the complete trak */
9649   if (stream->n_segments == 0) {
9650     GstClockTime stream_duration =
9651         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9652
9653     if (stream->segments == NULL)
9654       stream->segments = g_new (QtDemuxSegment, 1);
9655
9656     /* represent unknown our way */
9657     if (stream_duration == 0)
9658       stream_duration = GST_CLOCK_TIME_NONE;
9659
9660     stream->segments[0].time = 0;
9661     stream->segments[0].stop_time = stream_duration;
9662     stream->segments[0].duration = stream_duration;
9663     stream->segments[0].media_start = 0;
9664     stream->segments[0].media_stop = stream_duration;
9665     stream->segments[0].rate = 1.0;
9666     stream->segments[0].trak_media_start = 0;
9667
9668     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9669         GST_TIME_ARGS (stream_duration));
9670     stream->n_segments = 1;
9671     stream->dummy_segment = TRUE;
9672   }
9673   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9674
9675   return TRUE;
9676 }
9677
9678 /*
9679  * Parses the stsd atom of a svq3 trak looking for
9680  * the SMI and gama atoms.
9681  */
9682 static void
9683 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9684     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9685 {
9686   const guint8 *_gamma = NULL;
9687   GstBuffer *_seqh = NULL;
9688   const guint8 *stsd_data = stsd_entry_data;
9689   guint32 length = QT_UINT32 (stsd_data);
9690   guint16 version;
9691
9692   if (length < 32) {
9693     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9694     goto end;
9695   }
9696
9697   stsd_data += 16;
9698   length -= 16;
9699   version = QT_UINT16 (stsd_data);
9700   if (version == 3) {
9701     if (length >= 70) {
9702       length -= 70;
9703       stsd_data += 70;
9704       while (length > 8) {
9705         guint32 fourcc, size;
9706         const guint8 *data;
9707         size = QT_UINT32 (stsd_data);
9708         fourcc = QT_FOURCC (stsd_data + 4);
9709         data = stsd_data + 8;
9710
9711         if (size == 0) {
9712           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9713               "svq3 atom parsing");
9714           goto end;
9715         }
9716
9717         switch (fourcc) {
9718           case FOURCC_gama:{
9719             if (size == 12) {
9720               _gamma = data;
9721             } else {
9722               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9723                   " for gama atom, expected 12", size);
9724             }
9725             break;
9726           }
9727           case FOURCC_SMI_:{
9728             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9729               guint32 seqh_size;
9730               if (_seqh != NULL) {
9731                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9732                     " found, ignoring");
9733               } else {
9734                 seqh_size = QT_UINT32 (data + 4);
9735                 if (seqh_size > 0) {
9736                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9737                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9738                 }
9739               }
9740             }
9741             break;
9742           }
9743           default:{
9744             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9745                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9746           }
9747         }
9748
9749         if (size <= length) {
9750           length -= size;
9751           stsd_data += size;
9752         }
9753       }
9754     } else {
9755       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9756     }
9757   } else {
9758     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9759         G_GUINT16_FORMAT, version);
9760     goto end;
9761   }
9762
9763 end:
9764   if (gamma) {
9765     *gamma = _gamma;
9766   }
9767   if (seqh) {
9768     *seqh = _seqh;
9769   } else if (_seqh) {
9770     gst_buffer_unref (_seqh);
9771   }
9772 }
9773
9774 static gchar *
9775 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9776 {
9777   GNode *dinf;
9778   GstByteReader dref;
9779   gchar *uri = NULL;
9780
9781   /*
9782    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9783    * atom that might contain a 'data' atom with the rtsp uri.
9784    * This case was reported in bug #597497, some info about
9785    * the hndl atom can be found in TN1195
9786    */
9787   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9788   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9789
9790   if (dinf) {
9791     guint32 dref_num_entries = 0;
9792     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9793         gst_byte_reader_skip (&dref, 4) &&
9794         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9795       gint i;
9796
9797       /* search dref entries for hndl atom */
9798       for (i = 0; i < dref_num_entries; i++) {
9799         guint32 size = 0, type;
9800         guint8 string_len = 0;
9801         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9802             qt_atom_parser_get_fourcc (&dref, &type)) {
9803           if (type == FOURCC_hndl) {
9804             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9805
9806             /* skip data reference handle bytes and the
9807              * following pascal string and some extra 4
9808              * bytes I have no idea what are */
9809             if (!gst_byte_reader_skip (&dref, 4) ||
9810                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9811                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9812               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9813               break;
9814             }
9815
9816             /* iterate over the atoms to find the data atom */
9817             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9818               guint32 atom_size;
9819               guint32 atom_type;
9820
9821               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9822                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9823                 if (atom_type == FOURCC_data) {
9824                   const guint8 *uri_aux = NULL;
9825
9826                   /* found the data atom that might contain the rtsp uri */
9827                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9828                       "hndl atom, interpreting it as an URI");
9829                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9830                           &uri_aux)) {
9831                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9832                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9833                     else
9834                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9835                           "didn't contain a rtsp address");
9836                   } else {
9837                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9838                         "atom contents");
9839                   }
9840                   break;
9841                 }
9842                 /* skipping to the next entry */
9843                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9844                   break;
9845               } else {
9846                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9847                     "atom header");
9848                 break;
9849               }
9850             }
9851             break;
9852           }
9853           /* skip to the next entry */
9854           if (!gst_byte_reader_skip (&dref, size - 8))
9855             break;
9856         } else {
9857           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9858         }
9859       }
9860       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9861     }
9862   }
9863   return uri;
9864 }
9865
9866 #define AMR_NB_ALL_MODES        0x81ff
9867 #define AMR_WB_ALL_MODES        0x83ff
9868 static guint
9869 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9870 {
9871   /* The 'damr' atom is of the form:
9872    *
9873    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9874    *    32 b       8 b          16 b           8 b                 8 b
9875    *
9876    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9877    * represents the highest mode used in the stream (and thus the maximum
9878    * bitrate), with a couple of special cases as seen below.
9879    */
9880
9881   /* Map of frame type ID -> bitrate */
9882   static const guint nb_bitrates[] = {
9883     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9884   };
9885   static const guint wb_bitrates[] = {
9886     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9887   };
9888   GstMapInfo map;
9889   gsize max_mode;
9890   guint16 mode_set;
9891
9892   gst_buffer_map (buf, &map, GST_MAP_READ);
9893
9894   if (map.size != 0x11) {
9895     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9896     goto bad_data;
9897   }
9898
9899   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9900     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9901         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9902     goto bad_data;
9903   }
9904
9905   mode_set = QT_UINT16 (map.data + 13);
9906
9907   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9908     max_mode = 7 + (wb ? 1 : 0);
9909   else
9910     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9911     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9912
9913   if (max_mode == -1) {
9914     GST_DEBUG ("No mode indication was found (mode set) = %x",
9915         (guint) mode_set);
9916     goto bad_data;
9917   }
9918
9919   gst_buffer_unmap (buf, &map);
9920   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9921
9922 bad_data:
9923   gst_buffer_unmap (buf, &map);
9924   return 0;
9925 }
9926
9927 static gboolean
9928 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9929     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9930 {
9931   /*
9932    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9933    * [0 1 2]
9934    * [3 4 5]
9935    * [6 7 8]
9936    */
9937
9938   if (gst_byte_reader_get_remaining (reader) < 36)
9939     return FALSE;
9940
9941   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9942   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9943   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9944   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9945   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9946   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9947   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9948   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9949   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9950
9951   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9952   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9953       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9954       matrix[2] & 0xFF);
9955   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9956       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9957       matrix[5] & 0xFF);
9958   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9959       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9960       matrix[8] & 0xFF);
9961
9962   return TRUE;
9963 }
9964
9965 static void
9966 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9967     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9968 {
9969
9970 /* [a b c]
9971  * [d e f]
9972  * [g h i]
9973  *
9974  * This macro will only compare value abdegh, it expects cfi to have already
9975  * been checked
9976  */
9977 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9978                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9979
9980   /* only handle the cases where the last column has standard values */
9981   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9982     const gchar *rotation_tag = NULL;
9983
9984     /* no rotation needed */
9985     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9986       /* NOP */
9987     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9988       rotation_tag = "rotate-90";
9989     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9990       rotation_tag = "rotate-180";
9991     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9992       rotation_tag = "rotate-270";
9993     } else {
9994       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9995     }
9996
9997     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9998         rotation_tag);
9999     if (rotation_tag != NULL) {
10000       if (*taglist == NULL)
10001         *taglist = gst_tag_list_new_empty ();
10002       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10003           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10004     }
10005   } else {
10006     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10007   }
10008 }
10009
10010 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10011  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10012  * Common Encryption (cenc), the function will also parse the tenc box (defined
10013  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10014  * (typically an enc[v|a|t|s] sample entry); the function will set
10015  * @original_fmt to the fourcc of the original unencrypted stream format.
10016  * Returns TRUE if successful; FALSE otherwise. */
10017 static gboolean
10018 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10019     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10020 {
10021   GNode *sinf;
10022   GNode *frma;
10023   GNode *schm;
10024   GNode *schi;
10025
10026   g_return_val_if_fail (qtdemux != NULL, FALSE);
10027   g_return_val_if_fail (stream != NULL, FALSE);
10028   g_return_val_if_fail (container != NULL, FALSE);
10029   g_return_val_if_fail (original_fmt != NULL, FALSE);
10030
10031   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10032   if (G_UNLIKELY (!sinf)) {
10033     if (stream->protection_scheme_type == FOURCC_cenc) {
10034       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10035           "mandatory for Common Encryption");
10036       return FALSE;
10037     }
10038     return TRUE;
10039   }
10040
10041   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10042   if (G_UNLIKELY (!frma)) {
10043     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10044     return FALSE;
10045   }
10046
10047   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10048   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10049       GST_FOURCC_ARGS (*original_fmt));
10050
10051   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10052   if (!schm) {
10053     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10054     return FALSE;
10055   }
10056   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10057   stream->protection_scheme_version =
10058       QT_UINT32 ((const guint8 *) schm->data + 16);
10059
10060   GST_DEBUG_OBJECT (qtdemux,
10061       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10062       "protection_scheme_version: %#010x",
10063       GST_FOURCC_ARGS (stream->protection_scheme_type),
10064       stream->protection_scheme_version);
10065
10066   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10067   if (!schi) {
10068     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10069     return FALSE;
10070   }
10071   if (stream->protection_scheme_type == FOURCC_cenc) {
10072     QtDemuxCencSampleSetInfo *info;
10073     GNode *tenc;
10074     const guint8 *tenc_data;
10075     guint32 isEncrypted;
10076     guint8 iv_size;
10077     const guint8 *default_kid;
10078     GstBuffer *kid_buf;
10079
10080     if (G_UNLIKELY (!stream->protection_scheme_info))
10081       stream->protection_scheme_info =
10082           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10083
10084     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10085
10086     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10087     if (!tenc) {
10088       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10089           "which is mandatory for Common Encryption");
10090       return FALSE;
10091     }
10092     tenc_data = (const guint8 *) tenc->data + 12;
10093     isEncrypted = QT_UINT24 (tenc_data);
10094     iv_size = QT_UINT8 (tenc_data + 3);
10095     default_kid = (tenc_data + 4);
10096     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
10097     gst_buffer_fill (kid_buf, 0, default_kid, 16);
10098     if (info->default_properties)
10099       gst_structure_free (info->default_properties);
10100     info->default_properties =
10101         gst_structure_new ("application/x-cenc",
10102         "iv_size", G_TYPE_UINT, iv_size,
10103         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
10104         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
10105     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
10106         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
10107     gst_buffer_unref (kid_buf);
10108   }
10109   return TRUE;
10110 }
10111
10112 /* parse the traks.
10113  * With each track we associate a new QtDemuxStream that contains all the info
10114  * about the trak.
10115  * traks that do not decode to something (like strm traks) will not have a pad.
10116  */
10117 static gboolean
10118 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10119 {
10120   GstByteReader tkhd;
10121   int offset;
10122   GNode *mdia;
10123   GNode *mdhd;
10124   GNode *hdlr;
10125   GNode *minf;
10126   GNode *stbl;
10127   GNode *stsd;
10128   GNode *mp4a;
10129   GNode *mp4v;
10130   GNode *wave;
10131   GNode *esds;
10132   GNode *pasp;
10133   GNode *colr;
10134   GNode *tref;
10135   GNode *udta;
10136   GNode *svmi;
10137   GNode *fiel;
10138
10139   QtDemuxStream *stream = NULL;
10140   gboolean new_stream = FALSE;
10141   gchar *codec = NULL;
10142   const guint8 *stsd_data;
10143   const guint8 *stsd_entry_data;
10144   guint remaining_stsd_len;
10145   guint stsd_entry_count;
10146   guint stsd_index;
10147   guint16 lang_code;            /* quicktime lang code or packed iso code */
10148   guint32 version;
10149   guint32 tkhd_flags = 0;
10150   guint8 tkhd_version = 0;
10151   guint32 w = 0, h = 0;
10152   guint32 fourcc;
10153   guint value_size, stsd_len, len;
10154   guint32 track_id;
10155   guint32 dummy;
10156
10157   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10158
10159   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10160       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10161       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10162     goto corrupt_file;
10163
10164   /* pick between 64 or 32 bits */
10165   value_size = tkhd_version == 1 ? 8 : 4;
10166   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10167       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10168     goto corrupt_file;
10169
10170   if (!qtdemux->got_moov) {
10171     if (qtdemux_find_stream (qtdemux, track_id))
10172       goto existing_stream;
10173     stream = _create_stream ();
10174     stream->track_id = track_id;
10175     new_stream = TRUE;
10176   } else {
10177     stream = qtdemux_find_stream (qtdemux, track_id);
10178     if (!stream) {
10179       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
10180       goto skip_track;
10181     }
10182
10183     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10184
10185     /* flush samples data from this track from previous moov */
10186     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
10187     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
10188   }
10189   /* need defaults for fragments */
10190   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10191
10192   if ((tkhd_flags & 1) == 0)
10193     stream->disabled = TRUE;
10194
10195   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10196       tkhd_version, tkhd_flags, stream->track_id);
10197
10198   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10199     goto corrupt_file;
10200
10201   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10202     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10203     if (qtdemux->major_brand != FOURCC_mjp2 ||
10204         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10205       goto corrupt_file;
10206   }
10207
10208   len = QT_UINT32 ((guint8 *) mdhd->data);
10209   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10210   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10211   if (version == 0x01000000) {
10212     if (len < 38)
10213       goto corrupt_file;
10214     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10215     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10216     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10217   } else {
10218     if (len < 30)
10219       goto corrupt_file;
10220     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10221     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10222     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10223   }
10224
10225   if (lang_code < 0x400) {
10226     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10227   } else if (lang_code == 0x7fff) {
10228     stream->lang_id[0] = 0;     /* unspecified */
10229   } else {
10230     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10231     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10232     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10233     stream->lang_id[3] = 0;
10234   }
10235
10236   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10237       stream->timescale);
10238   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10239       stream->duration);
10240   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10241       lang_code, stream->lang_id);
10242
10243   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10244     goto corrupt_file;
10245
10246   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10247     /* chapters track reference */
10248     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10249     if (chap) {
10250       gsize length = GST_READ_UINT32_BE (chap->data);
10251       if (qtdemux->chapters_track_id)
10252         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10253
10254       if (length >= 12) {
10255         qtdemux->chapters_track_id =
10256             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10257       }
10258     }
10259   }
10260
10261   /* fragmented files may have bogus duration in moov */
10262   if (!qtdemux->fragmented &&
10263       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10264     guint64 tdur1, tdur2;
10265
10266     /* don't overflow */
10267     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10268     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10269
10270     /* HACK:
10271      * some of those trailers, nowadays, have prologue images that are
10272      * themselves video tracks as well. I haven't really found a way to
10273      * identify those yet, except for just looking at their duration. */
10274     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10275       GST_WARNING_OBJECT (qtdemux,
10276           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10277           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10278           "found, assuming preview image or something; skipping track",
10279           stream->duration, stream->timescale, qtdemux->duration,
10280           qtdemux->timescale);
10281       if (new_stream)
10282         gst_qtdemux_stream_free (qtdemux, stream);
10283       return TRUE;
10284     }
10285   }
10286
10287   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10288     goto corrupt_file;
10289
10290   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10291       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10292
10293   len = QT_UINT32 ((guint8 *) hdlr->data);
10294   if (len >= 20)
10295     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10296   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10297       GST_FOURCC_ARGS (stream->subtype));
10298
10299   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10300     goto corrupt_file;
10301
10302   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10303     goto corrupt_file;
10304
10305   /*parse svmi header if existing */
10306   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10307   if (svmi) {
10308     len = QT_UINT32 ((guint8 *) svmi->data);
10309     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10310     if (!version) {
10311       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10312       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10313       guint8 frame_type, frame_layout;
10314
10315       /* MPEG-A stereo video */
10316       if (qtdemux->major_brand == FOURCC_ss02)
10317         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10318
10319       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10320       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10321       switch (frame_type) {
10322         case 0:
10323           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10324           break;
10325         case 1:
10326           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10327           break;
10328         case 2:
10329           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10330           break;
10331         case 3:
10332           /* mode 3 is primary/secondary view sequence, ie
10333            * left/right views in separate tracks. See section 7.2
10334            * of ISO/IEC 23000-11:2009 */
10335           GST_FIXME_OBJECT (qtdemux,
10336               "Implement stereo video in separate streams");
10337       }
10338
10339       if ((frame_layout & 0x1) == 0)
10340         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10341
10342       GST_LOG_OBJECT (qtdemux,
10343           "StereoVideo: composition type: %u, is_left_first: %u",
10344           frame_type, frame_layout);
10345       stream->multiview_mode = mode;
10346       stream->multiview_flags = flags;
10347     }
10348   }
10349
10350   /* parse rest of tkhd */
10351   if (stream->subtype == FOURCC_vide) {
10352     guint32 matrix[9];
10353
10354     /* version 1 uses some 64-bit ints */
10355     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10356       goto corrupt_file;
10357
10358     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10359       goto corrupt_file;
10360
10361     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10362         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10363       goto corrupt_file;
10364
10365     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10366         &stream->stream_tags);
10367   }
10368
10369   /* parse stsd */
10370   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10371     goto corrupt_file;
10372   stsd_data = (const guint8 *) stsd->data;
10373
10374   /* stsd should at least have one entry */
10375   stsd_len = QT_UINT32 (stsd_data);
10376   if (stsd_len < 24) {
10377     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10378     if (stream->subtype == FOURCC_vivo) {
10379       if (new_stream)
10380         gst_qtdemux_stream_free (qtdemux, stream);
10381       return TRUE;
10382     } else {
10383       goto corrupt_file;
10384     }
10385   }
10386
10387   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10388   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10389   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10390   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10391
10392   stsd_entry_data = stsd_data + 16;
10393   remaining_stsd_len = stsd_len - 16;
10394   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10395     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10396
10397     /* and that entry should fit within stsd */
10398     len = QT_UINT32 (stsd_entry_data);
10399     if (len > remaining_stsd_len)
10400       goto corrupt_file;
10401
10402     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10403     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10404         GST_FOURCC_ARGS (entry->fourcc));
10405     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10406
10407     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10408       goto error_encrypted;
10409
10410     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10411       /* FIXME this looks wrong, there might be multiple children
10412        * with the same type */
10413       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10414       stream->protected = TRUE;
10415       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10416         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10417     }
10418
10419     if (stream->subtype == FOURCC_vide) {
10420       gboolean gray;
10421       gint depth, palette_size, palette_count;
10422       guint32 *palette_data = NULL;
10423
10424       entry->sampled = TRUE;
10425
10426       stream->display_width = w >> 16;
10427       stream->display_height = h >> 16;
10428
10429       offset = 16;
10430       if (len < 86)             /* TODO verify */
10431         goto corrupt_file;
10432
10433       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10434       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10435       entry->fps_n = 0;         /* this is filled in later */
10436       entry->fps_d = 0;         /* this is filled in later */
10437       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10438       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10439
10440       /* if color_table_id is 0, ctab atom must follow; however some files
10441        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10442        * if color table is not present we'll correct the value */
10443       if (entry->color_table_id == 0 &&
10444           (len < 90
10445               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10446         entry->color_table_id = -1;
10447       }
10448
10449       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10450           entry->width, entry->height, entry->bits_per_sample,
10451           entry->color_table_id);
10452
10453       depth = entry->bits_per_sample;
10454
10455       /* more than 32 bits means grayscale */
10456       gray = (depth > 32);
10457       /* low 32 bits specify the depth  */
10458       depth &= 0x1F;
10459
10460       /* different number of palette entries is determined by depth. */
10461       palette_count = 0;
10462       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10463         palette_count = (1 << depth);
10464       palette_size = palette_count * 4;
10465
10466       if (entry->color_table_id) {
10467         switch (palette_count) {
10468           case 0:
10469             break;
10470           case 2:
10471             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10472             break;
10473           case 4:
10474             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10475             break;
10476           case 16:
10477             if (gray)
10478               palette_data =
10479                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10480             else
10481               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10482             break;
10483           case 256:
10484             if (gray)
10485               palette_data =
10486                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10487             else
10488               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10489             break;
10490           default:
10491             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10492                 (_("The video in this file might not play correctly.")),
10493                 ("unsupported palette depth %d", depth));
10494             break;
10495         }
10496       } else {
10497         gint i, j, start, end;
10498
10499         if (len < 94)
10500           goto corrupt_file;
10501
10502         /* read table */
10503         start = QT_UINT32 (stsd_entry_data + offset + 70);
10504         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10505         end = QT_UINT16 (stsd_entry_data + offset + 76);
10506
10507         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10508             start, end, palette_count);
10509
10510         if (end > 255)
10511           end = 255;
10512         if (start > end)
10513           start = end;
10514
10515         if (len < 94 + (end - start) * 8)
10516           goto corrupt_file;
10517
10518         /* palette is always the same size */
10519         palette_data = g_malloc0 (256 * 4);
10520         palette_size = 256 * 4;
10521
10522         for (j = 0, i = start; i <= end; j++, i++) {
10523           guint32 a, r, g, b;
10524
10525           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10526           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10527           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10528           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10529
10530           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10531               (g & 0xff00) | (b >> 8);
10532         }
10533       }
10534
10535       if (entry->caps)
10536         gst_caps_unref (entry->caps);
10537
10538       entry->caps =
10539           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10540           &codec);
10541       if (G_UNLIKELY (!entry->caps)) {
10542         g_free (palette_data);
10543         goto unknown_stream;
10544       }
10545
10546       if (codec) {
10547         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10548             GST_TAG_VIDEO_CODEC, codec, NULL);
10549         g_free (codec);
10550         codec = NULL;
10551       }
10552
10553       if (palette_data) {
10554         GstStructure *s;
10555
10556         if (entry->rgb8_palette)
10557           gst_memory_unref (entry->rgb8_palette);
10558         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10559             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10560
10561         s = gst_caps_get_structure (entry->caps, 0);
10562
10563         /* non-raw video has a palette_data property. raw video has the palette as
10564          * an extra plane that we append to the output buffers before we push
10565          * them*/
10566         if (!gst_structure_has_name (s, "video/x-raw")) {
10567           GstBuffer *palette;
10568
10569           palette = gst_buffer_new ();
10570           gst_buffer_append_memory (palette, entry->rgb8_palette);
10571           entry->rgb8_palette = NULL;
10572
10573           gst_caps_set_simple (entry->caps, "palette_data",
10574               GST_TYPE_BUFFER, palette, NULL);
10575           gst_buffer_unref (palette);
10576         }
10577       } else if (palette_count != 0) {
10578         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10579             (NULL), ("Unsupported palette depth %d", depth));
10580       }
10581
10582       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10583           QT_UINT16 (stsd_entry_data + offset + 32));
10584
10585       esds = NULL;
10586       pasp = NULL;
10587       colr = NULL;
10588       fiel = NULL;
10589       /* pick 'the' stsd child */
10590       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10591       if (!stream->protected) {
10592         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10593           mp4v = NULL;
10594         }
10595       } else {
10596         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10597           mp4v = NULL;
10598         }
10599       }
10600
10601       if (mp4v) {
10602         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10603         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10604         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10605         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10606       }
10607
10608       if (pasp) {
10609         const guint8 *pasp_data = (const guint8 *) pasp->data;
10610         gint len = QT_UINT32 (pasp_data);
10611
10612         if (len == 16) {
10613           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10614           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10615         } else {
10616           CUR_STREAM (stream)->par_w = 0;
10617           CUR_STREAM (stream)->par_h = 0;
10618         }
10619       } else {
10620         CUR_STREAM (stream)->par_w = 0;
10621         CUR_STREAM (stream)->par_h = 0;
10622       }
10623
10624       if (fiel) {
10625         const guint8 *fiel_data = (const guint8 *) fiel->data;
10626         gint len = QT_UINT32 (fiel_data);
10627
10628         if (len == 10) {
10629           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10630           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10631         }
10632       }
10633
10634       if (colr) {
10635         const guint8 *colr_data = (const guint8 *) colr->data;
10636         gint len = QT_UINT32 (colr_data);
10637
10638         if (len == 19 || len == 18) {
10639           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10640
10641           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10642             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10643             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10644             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10645             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10646
10647             switch (primaries) {
10648               case 1:
10649                 CUR_STREAM (stream)->colorimetry.primaries =
10650                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10651                 break;
10652               case 5:
10653                 CUR_STREAM (stream)->colorimetry.primaries =
10654                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10655                 break;
10656               case 6:
10657                 CUR_STREAM (stream)->colorimetry.primaries =
10658                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10659                 break;
10660               case 9:
10661                 CUR_STREAM (stream)->colorimetry.primaries =
10662                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10663                 break;
10664               default:
10665                 break;
10666             }
10667
10668             switch (transfer_function) {
10669               case 1:
10670                 CUR_STREAM (stream)->colorimetry.transfer =
10671                     GST_VIDEO_TRANSFER_BT709;
10672                 break;
10673               case 7:
10674                 CUR_STREAM (stream)->colorimetry.transfer =
10675                     GST_VIDEO_TRANSFER_SMPTE240M;
10676                 break;
10677               default:
10678                 break;
10679             }
10680
10681             switch (matrix) {
10682               case 1:
10683                 CUR_STREAM (stream)->colorimetry.matrix =
10684                     GST_VIDEO_COLOR_MATRIX_BT709;
10685                 break;
10686               case 6:
10687                 CUR_STREAM (stream)->colorimetry.matrix =
10688                     GST_VIDEO_COLOR_MATRIX_BT601;
10689                 break;
10690               case 7:
10691                 CUR_STREAM (stream)->colorimetry.matrix =
10692                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10693                 break;
10694               case 9:
10695                 CUR_STREAM (stream)->colorimetry.matrix =
10696                     GST_VIDEO_COLOR_MATRIX_BT2020;
10697                 break;
10698               default:
10699                 break;
10700             }
10701
10702             CUR_STREAM (stream)->colorimetry.range =
10703                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10704                 GST_VIDEO_COLOR_RANGE_16_235;
10705           } else {
10706             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10707           }
10708         } else {
10709           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10710         }
10711       }
10712
10713       if (esds) {
10714         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10715             stream->stream_tags);
10716       } else {
10717         switch (fourcc) {
10718           case FOURCC_H264:
10719           case FOURCC_avc1:
10720           case FOURCC_avc3:
10721           {
10722             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10723             const guint8 *avc_data = stsd_entry_data + 0x56;
10724
10725             /* find avcC */
10726             while (len >= 0x8) {
10727               gint size;
10728
10729               if (QT_UINT32 (avc_data) <= len)
10730                 size = QT_UINT32 (avc_data) - 0x8;
10731               else
10732                 size = len - 0x8;
10733
10734               if (size < 1)
10735                 /* No real data, so break out */
10736                 break;
10737
10738               switch (QT_FOURCC (avc_data + 0x4)) {
10739                 case FOURCC_avcC:
10740                 {
10741                   /* parse, if found */
10742                   GstBuffer *buf;
10743
10744                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10745
10746                   /* First 4 bytes are the length of the atom, the next 4 bytes
10747                    * are the fourcc, the next 1 byte is the version, and the
10748                    * subsequent bytes are profile_tier_level structure like data. */
10749                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10750                       avc_data + 8 + 1, size - 1);
10751                   buf = gst_buffer_new_and_alloc (size);
10752                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10753                   gst_caps_set_simple (entry->caps,
10754                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10755                   gst_buffer_unref (buf);
10756
10757                   break;
10758                 }
10759                 case FOURCC_strf:
10760                 {
10761                   GstBuffer *buf;
10762
10763                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10764
10765                   /* First 4 bytes are the length of the atom, the next 4 bytes
10766                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10767                    * next 1 byte is the version, and the
10768                    * subsequent bytes are sequence parameter set like data. */
10769
10770                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10771                   if (size > 1) {
10772                     gst_codec_utils_h264_caps_set_level_and_profile
10773                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10774
10775                     buf = gst_buffer_new_and_alloc (size);
10776                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10777                     gst_caps_set_simple (entry->caps,
10778                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10779                     gst_buffer_unref (buf);
10780                   }
10781                   break;
10782                 }
10783                 case FOURCC_btrt:
10784                 {
10785                   guint avg_bitrate, max_bitrate;
10786
10787                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10788                   if (size < 12)
10789                     break;
10790
10791                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10792                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10793
10794                   if (!max_bitrate && !avg_bitrate)
10795                     break;
10796
10797                   /* Some muxers seem to swap the average and maximum bitrates
10798                    * (I'm looking at you, YouTube), so we swap for sanity. */
10799                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10800                     guint temp = avg_bitrate;
10801
10802                     avg_bitrate = max_bitrate;
10803                     max_bitrate = temp;
10804                   }
10805
10806                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10807                     gst_tag_list_add (stream->stream_tags,
10808                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10809                         max_bitrate, NULL);
10810                   }
10811                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10812                     gst_tag_list_add (stream->stream_tags,
10813                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10814                         NULL);
10815                   }
10816
10817                   break;
10818                 }
10819
10820                 default:
10821                   break;
10822               }
10823
10824               len -= size + 8;
10825               avc_data += size + 8;
10826             }
10827
10828             break;
10829           }
10830           case FOURCC_H265:
10831           case FOURCC_hvc1:
10832           case FOURCC_hev1:
10833           {
10834             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10835             const guint8 *hevc_data = stsd_entry_data + 0x56;
10836
10837             /* find hevc */
10838             while (len >= 0x8) {
10839               gint size;
10840
10841               if (QT_UINT32 (hevc_data) <= len)
10842                 size = QT_UINT32 (hevc_data) - 0x8;
10843               else
10844                 size = len - 0x8;
10845
10846               if (size < 1)
10847                 /* No real data, so break out */
10848                 break;
10849
10850               switch (QT_FOURCC (hevc_data + 0x4)) {
10851                 case FOURCC_hvcC:
10852                 {
10853                   /* parse, if found */
10854                   GstBuffer *buf;
10855
10856                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10857
10858                   /* First 4 bytes are the length of the atom, the next 4 bytes
10859                    * are the fourcc, the next 1 byte is the version, and the
10860                    * subsequent bytes are sequence parameter set like data. */
10861                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10862                       (entry->caps, hevc_data + 8 + 1, size - 1);
10863
10864                   buf = gst_buffer_new_and_alloc (size);
10865                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10866                   gst_caps_set_simple (entry->caps,
10867                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10868                   gst_buffer_unref (buf);
10869                   break;
10870                 }
10871                 default:
10872                   break;
10873               }
10874               len -= size + 8;
10875               hevc_data += size + 8;
10876             }
10877             break;
10878           }
10879           case FOURCC_mp4v:
10880           case FOURCC_MP4V:
10881           case FOURCC_fmp4:
10882           case FOURCC_FMP4:
10883           case FOURCC_xvid:
10884           case FOURCC_XVID:
10885           {
10886             GNode *glbl;
10887
10888             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10889                 GST_FOURCC_ARGS (fourcc));
10890
10891             /* codec data might be in glbl extension atom */
10892             glbl = mp4v ?
10893                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10894             if (glbl) {
10895               guint8 *data;
10896               GstBuffer *buf;
10897               gint len;
10898
10899               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10900               data = glbl->data;
10901               len = QT_UINT32 (data);
10902               if (len > 0x8) {
10903                 len -= 0x8;
10904                 buf = gst_buffer_new_and_alloc (len);
10905                 gst_buffer_fill (buf, 0, data + 8, len);
10906                 gst_caps_set_simple (entry->caps,
10907                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10908                 gst_buffer_unref (buf);
10909               }
10910             }
10911             break;
10912           }
10913           case FOURCC_mjp2:
10914           {
10915             /* see annex I of the jpeg2000 spec */
10916             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10917             const guint8 *data;
10918             const gchar *colorspace = NULL;
10919             gint ncomp = 0;
10920             guint32 ncomp_map = 0;
10921             gint32 *comp_map = NULL;
10922             guint32 nchan_def = 0;
10923             gint32 *chan_def = NULL;
10924
10925             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10926             /* some required atoms */
10927             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10928             if (!mjp2)
10929               break;
10930             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10931             if (!jp2h)
10932               break;
10933
10934             /* number of components; redundant with info in codestream, but useful
10935                to a muxer */
10936             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10937             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10938               break;
10939             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10940
10941             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10942             if (!colr)
10943               break;
10944             GST_DEBUG_OBJECT (qtdemux, "found colr");
10945             /* extract colour space info */
10946             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10947               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10948                 case 16:
10949                   colorspace = "sRGB";
10950                   break;
10951                 case 17:
10952                   colorspace = "GRAY";
10953                   break;
10954                 case 18:
10955                   colorspace = "sYUV";
10956                   break;
10957                 default:
10958                   colorspace = NULL;
10959                   break;
10960               }
10961             }
10962             if (!colorspace)
10963               /* colr is required, and only values 16, 17, and 18 are specified,
10964                  so error if we have no colorspace */
10965               break;
10966
10967             /* extract component mapping */
10968             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10969             if (cmap) {
10970               guint32 cmap_len = 0;
10971               int i;
10972               cmap_len = QT_UINT32 (cmap->data);
10973               if (cmap_len >= 8) {
10974                 /* normal box, subtract off header */
10975                 cmap_len -= 8;
10976                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10977                 if (cmap_len % 4 == 0) {
10978                   ncomp_map = (cmap_len / 4);
10979                   comp_map = g_new0 (gint32, ncomp_map);
10980                   for (i = 0; i < ncomp_map; i++) {
10981                     guint16 cmp;
10982                     guint8 mtyp, pcol;
10983                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10984                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10985                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10986                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10987                   }
10988                 }
10989               }
10990             }
10991             /* extract channel definitions */
10992             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10993             if (cdef) {
10994               guint32 cdef_len = 0;
10995               int i;
10996               cdef_len = QT_UINT32 (cdef->data);
10997               if (cdef_len >= 10) {
10998                 /* normal box, subtract off header and len */
10999                 cdef_len -= 10;
11000                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11001                 if (cdef_len % 6 == 0) {
11002                   nchan_def = (cdef_len / 6);
11003                   chan_def = g_new0 (gint32, nchan_def);
11004                   for (i = 0; i < nchan_def; i++)
11005                     chan_def[i] = -1;
11006                   for (i = 0; i < nchan_def; i++) {
11007                     guint16 cn, typ, asoc;
11008                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11009                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11010                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11011                     if (cn < nchan_def) {
11012                       switch (typ) {
11013                         case 0:
11014                           chan_def[cn] = asoc;
11015                           break;
11016                         case 1:
11017                           chan_def[cn] = 0;     /* alpha */
11018                           break;
11019                         default:
11020                           chan_def[cn] = -typ;
11021                       }
11022                     }
11023                   }
11024                 }
11025               }
11026             }
11027
11028             gst_caps_set_simple (entry->caps,
11029                 "num-components", G_TYPE_INT, ncomp, NULL);
11030             gst_caps_set_simple (entry->caps,
11031                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11032
11033             if (comp_map) {
11034               GValue arr = { 0, };
11035               GValue elt = { 0, };
11036               int i;
11037               g_value_init (&arr, GST_TYPE_ARRAY);
11038               g_value_init (&elt, G_TYPE_INT);
11039               for (i = 0; i < ncomp_map; i++) {
11040                 g_value_set_int (&elt, comp_map[i]);
11041                 gst_value_array_append_value (&arr, &elt);
11042               }
11043               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11044                   "component-map", &arr);
11045               g_value_unset (&elt);
11046               g_value_unset (&arr);
11047               g_free (comp_map);
11048             }
11049
11050             if (chan_def) {
11051               GValue arr = { 0, };
11052               GValue elt = { 0, };
11053               int i;
11054               g_value_init (&arr, GST_TYPE_ARRAY);
11055               g_value_init (&elt, G_TYPE_INT);
11056               for (i = 0; i < nchan_def; i++) {
11057                 g_value_set_int (&elt, chan_def[i]);
11058                 gst_value_array_append_value (&arr, &elt);
11059               }
11060               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11061                   "channel-definitions", &arr);
11062               g_value_unset (&elt);
11063               g_value_unset (&arr);
11064               g_free (chan_def);
11065             }
11066
11067             /* some optional atoms */
11068             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11069             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11070
11071             /* indicate possible fields in caps */
11072             if (field) {
11073               data = (guint8 *) field->data + 8;
11074               if (*data != 1)
11075                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11076                     (gint) * data, NULL);
11077             }
11078             /* add codec_data if provided */
11079             if (prefix) {
11080               GstBuffer *buf;
11081               gint len;
11082
11083               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11084               data = prefix->data;
11085               len = QT_UINT32 (data);
11086               if (len > 0x8) {
11087                 len -= 0x8;
11088                 buf = gst_buffer_new_and_alloc (len);
11089                 gst_buffer_fill (buf, 0, data + 8, len);
11090                 gst_caps_set_simple (entry->caps,
11091                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11092                 gst_buffer_unref (buf);
11093               }
11094             }
11095             break;
11096           }
11097           case FOURCC_SVQ3:
11098           case FOURCC_VP31:
11099           {
11100             GstBuffer *buf;
11101             GstBuffer *seqh = NULL;
11102             const guint8 *gamma_data = NULL;
11103             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11104
11105             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11106                 &seqh);
11107             if (gamma_data) {
11108               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11109                   QT_FP32 (gamma_data), NULL);
11110             }
11111             if (seqh) {
11112               /* sorry for the bad name, but we don't know what this is, other
11113                * than its own fourcc */
11114               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11115                   NULL);
11116               gst_buffer_unref (seqh);
11117             }
11118
11119             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11120             buf = gst_buffer_new_and_alloc (len);
11121             gst_buffer_fill (buf, 0, stsd_data, len);
11122             gst_caps_set_simple (entry->caps,
11123                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11124             gst_buffer_unref (buf);
11125             break;
11126           }
11127           case FOURCC_jpeg:
11128           {
11129             /* https://developer.apple.com/standards/qtff-2001.pdf,
11130              * page 92, "Video Sample Description", under table 3.1 */
11131             GstByteReader br;
11132
11133             const gint compressor_offset =
11134                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11135             const gint min_size = compressor_offset + 32 + 2 + 2;
11136             GNode *jpeg;
11137             guint32 len;
11138             guint16 color_table_id = 0;
11139             gboolean ok;
11140
11141             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11142
11143             /* recover information on interlaced/progressive */
11144             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11145             if (!jpeg)
11146               break;
11147
11148             len = QT_UINT32 (jpeg->data);
11149             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11150                 min_size);
11151             if (len >= min_size) {
11152               gst_byte_reader_init (&br, jpeg->data, len);
11153
11154               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11155               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11156               if (color_table_id != 0) {
11157                 /* the spec says there can be concatenated chunks in the data, and we want
11158                  * to find one called field. Walk through them. */
11159                 gint offset = min_size;
11160                 while (offset + 8 < len) {
11161                   guint32 size = 0, tag;
11162                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11163                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11164                   if (!ok || size < 8) {
11165                     GST_WARNING_OBJECT (qtdemux,
11166                         "Failed to walk optional chunk list");
11167                     break;
11168                   }
11169                   GST_DEBUG_OBJECT (qtdemux,
11170                       "Found optional %4.4s chunk, size %u",
11171                       (const char *) &tag, size);
11172                   if (tag == FOURCC_fiel) {
11173                     guint8 n_fields = 0, ordering = 0;
11174                     gst_byte_reader_get_uint8 (&br, &n_fields);
11175                     gst_byte_reader_get_uint8 (&br, &ordering);
11176                     if (n_fields == 1 || n_fields == 2) {
11177                       GST_DEBUG_OBJECT (qtdemux,
11178                           "Found fiel tag with %u fields, ordering %u",
11179                           n_fields, ordering);
11180                       if (n_fields == 2)
11181                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11182                             "interlace-mode", G_TYPE_STRING, "interleaved",
11183                             NULL);
11184                     } else {
11185                       GST_WARNING_OBJECT (qtdemux,
11186                           "Found fiel tag with invalid fields (%u)", n_fields);
11187                     }
11188                   }
11189                   offset += size;
11190                 }
11191               } else {
11192                 GST_DEBUG_OBJECT (qtdemux,
11193                     "Color table ID is 0, not trying to get interlacedness");
11194               }
11195             } else {
11196               GST_WARNING_OBJECT (qtdemux,
11197                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11198             }
11199
11200             break;
11201           }
11202           case FOURCC_rle_:
11203           case FOURCC_WRLE:
11204           {
11205             gst_caps_set_simple (entry->caps,
11206                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11207                 NULL);
11208             break;
11209           }
11210           case FOURCC_XiTh:
11211           {
11212             GNode *xith, *xdxt;
11213
11214             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11215             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11216             if (!xith)
11217               break;
11218
11219             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11220             if (!xdxt)
11221               break;
11222
11223             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11224             /* collect the headers and store them in a stream list so that we can
11225              * send them out first */
11226             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11227             break;
11228           }
11229           case FOURCC_ovc1:
11230           {
11231             GNode *ovc1;
11232             guint8 *ovc1_data;
11233             guint ovc1_len;
11234             GstBuffer *buf;
11235
11236             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11237             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11238             if (!ovc1)
11239               break;
11240             ovc1_data = ovc1->data;
11241             ovc1_len = QT_UINT32 (ovc1_data);
11242             if (ovc1_len <= 198) {
11243               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11244               break;
11245             }
11246             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11247             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11248             gst_caps_set_simple (entry->caps,
11249                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11250             gst_buffer_unref (buf);
11251             break;
11252           }
11253           case FOURCC_vc_1:
11254           {
11255             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11256             const guint8 *vc1_data = stsd_entry_data + 0x56;
11257
11258             /* find dvc1 */
11259             while (len >= 8) {
11260               gint size;
11261
11262               if (QT_UINT32 (vc1_data) <= len)
11263                 size = QT_UINT32 (vc1_data) - 8;
11264               else
11265                 size = len - 8;
11266
11267               if (size < 1)
11268                 /* No real data, so break out */
11269                 break;
11270
11271               switch (QT_FOURCC (vc1_data + 0x4)) {
11272                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11273                 {
11274                   GstBuffer *buf;
11275
11276                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11277                   buf = gst_buffer_new_and_alloc (size);
11278                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11279                   gst_caps_set_simple (entry->caps,
11280                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11281                   gst_buffer_unref (buf);
11282                   break;
11283                 }
11284                 default:
11285                   break;
11286               }
11287               len -= size + 8;
11288               vc1_data += size + 8;
11289             }
11290             break;
11291           }
11292           default:
11293             break;
11294         }
11295       }
11296
11297       GST_INFO_OBJECT (qtdemux,
11298           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11299           GST_FOURCC_ARGS (fourcc), entry->caps);
11300
11301     } else if (stream->subtype == FOURCC_soun) {
11302       int version, samplesize;
11303       guint16 compression_id;
11304       gboolean amrwb = FALSE;
11305
11306       offset = 16;
11307       /* sample description entry (16) + sound sample description v0 (20) */
11308       if (len < 36)
11309         goto corrupt_file;
11310
11311       version = QT_UINT32 (stsd_entry_data + offset);
11312       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11313       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11314       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11315       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11316
11317       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11318       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11319           QT_UINT32 (stsd_entry_data + offset + 4));
11320       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11321       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11322       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11323       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11324           QT_UINT16 (stsd_entry_data + offset + 14));
11325       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11326
11327       if (compression_id == 0xfffe)
11328         entry->sampled = TRUE;
11329
11330       /* first assume uncompressed audio */
11331       entry->bytes_per_sample = samplesize / 8;
11332       entry->samples_per_frame = entry->n_channels;
11333       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11334       entry->samples_per_packet = entry->samples_per_frame;
11335       entry->bytes_per_packet = entry->bytes_per_sample;
11336
11337       offset = 36;
11338       switch (fourcc) {
11339           /* Yes, these have to be hard-coded */
11340         case FOURCC_MAC6:
11341         {
11342           entry->samples_per_packet = 6;
11343           entry->bytes_per_packet = 1;
11344           entry->bytes_per_frame = 1 * entry->n_channels;
11345           entry->bytes_per_sample = 1;
11346           entry->samples_per_frame = 6 * entry->n_channels;
11347           break;
11348         }
11349         case FOURCC_MAC3:
11350         {
11351           entry->samples_per_packet = 3;
11352           entry->bytes_per_packet = 1;
11353           entry->bytes_per_frame = 1 * entry->n_channels;
11354           entry->bytes_per_sample = 1;
11355           entry->samples_per_frame = 3 * entry->n_channels;
11356           break;
11357         }
11358         case FOURCC_ima4:
11359         {
11360           entry->samples_per_packet = 64;
11361           entry->bytes_per_packet = 34;
11362           entry->bytes_per_frame = 34 * entry->n_channels;
11363           entry->bytes_per_sample = 2;
11364           entry->samples_per_frame = 64 * entry->n_channels;
11365           break;
11366         }
11367         case FOURCC_ulaw:
11368         case FOURCC_alaw:
11369         {
11370           entry->samples_per_packet = 1;
11371           entry->bytes_per_packet = 1;
11372           entry->bytes_per_frame = 1 * entry->n_channels;
11373           entry->bytes_per_sample = 1;
11374           entry->samples_per_frame = 1 * entry->n_channels;
11375           break;
11376         }
11377         case FOURCC_agsm:
11378         {
11379           entry->samples_per_packet = 160;
11380           entry->bytes_per_packet = 33;
11381           entry->bytes_per_frame = 33 * entry->n_channels;
11382           entry->bytes_per_sample = 2;
11383           entry->samples_per_frame = 160 * entry->n_channels;
11384           break;
11385         }
11386         default:
11387           break;
11388       }
11389
11390       if (version == 0x00010000) {
11391         /* sample description entry (16) + sound sample description v1 (20+16) */
11392         if (len < 52)
11393           goto corrupt_file;
11394
11395         switch (fourcc) {
11396           case FOURCC_twos:
11397           case FOURCC_sowt:
11398           case FOURCC_raw_:
11399             break;
11400           default:
11401           {
11402             /* only parse extra decoding config for non-pcm audio */
11403             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11404             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11405             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11406             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11407
11408             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11409                 entry->samples_per_packet);
11410             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11411                 entry->bytes_per_packet);
11412             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11413                 entry->bytes_per_frame);
11414             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11415                 entry->bytes_per_sample);
11416
11417             if (!entry->sampled && entry->bytes_per_packet) {
11418               entry->samples_per_frame = (entry->bytes_per_frame /
11419                   entry->bytes_per_packet) * entry->samples_per_packet;
11420               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11421                   entry->samples_per_frame);
11422             }
11423             break;
11424           }
11425         }
11426       } else if (version == 0x00020000) {
11427         union
11428         {
11429           gdouble fp;
11430           guint64 val;
11431         } qtfp;
11432
11433         /* sample description entry (16) + sound sample description v2 (56) */
11434         if (len < 72)
11435           goto corrupt_file;
11436
11437         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11438         entry->rate = qtfp.fp;
11439         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11440
11441         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11442         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11443         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11444         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11445             QT_UINT32 (stsd_entry_data + offset + 20));
11446         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11447             QT_UINT32 (stsd_entry_data + offset + 24));
11448         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11449             QT_UINT32 (stsd_entry_data + offset + 28));
11450         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11451             QT_UINT32 (stsd_entry_data + offset + 32));
11452       } else if (version != 0x00000) {
11453         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11454             version);
11455       }
11456
11457       if (entry->caps)
11458         gst_caps_unref (entry->caps);
11459
11460       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11461           stsd_entry_data + 32, len - 16, &codec);
11462
11463       switch (fourcc) {
11464         case FOURCC_in24:
11465         {
11466           GNode *enda;
11467           GNode *in24;
11468
11469           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11470
11471           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11472           if (!enda) {
11473             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11474             if (wave)
11475               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11476           }
11477           if (enda) {
11478             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11479             gst_caps_set_simple (entry->caps,
11480                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11481                 NULL);
11482           }
11483           break;
11484         }
11485         case FOURCC_owma:
11486         {
11487           const guint8 *owma_data;
11488           const gchar *codec_name = NULL;
11489           guint owma_len;
11490           GstBuffer *buf;
11491           gint version = 1;
11492           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11493           /* FIXME this should also be gst_riff_strf_auds,
11494            * but the latter one is actually missing bits-per-sample :( */
11495           typedef struct
11496           {
11497             gint16 wFormatTag;
11498             gint16 nChannels;
11499             gint32 nSamplesPerSec;
11500             gint32 nAvgBytesPerSec;
11501             gint16 nBlockAlign;
11502             gint16 wBitsPerSample;
11503             gint16 cbSize;
11504           } WAVEFORMATEX;
11505           WAVEFORMATEX *wfex;
11506
11507           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11508           owma_data = stsd_entry_data;
11509           owma_len = QT_UINT32 (owma_data);
11510           if (owma_len <= 54) {
11511             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11512             break;
11513           }
11514           wfex = (WAVEFORMATEX *) (owma_data + 36);
11515           buf = gst_buffer_new_and_alloc (owma_len - 54);
11516           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11517           if (wfex->wFormatTag == 0x0161) {
11518             codec_name = "Windows Media Audio";
11519             version = 2;
11520           } else if (wfex->wFormatTag == 0x0162) {
11521             codec_name = "Windows Media Audio 9 Pro";
11522             version = 3;
11523           } else if (wfex->wFormatTag == 0x0163) {
11524             codec_name = "Windows Media Audio 9 Lossless";
11525             /* is that correct? gstffmpegcodecmap.c is missing it, but
11526              * fluendo codec seems to support it */
11527             version = 4;
11528           }
11529
11530           gst_caps_set_simple (entry->caps,
11531               "codec_data", GST_TYPE_BUFFER, buf,
11532               "wmaversion", G_TYPE_INT, version,
11533               "block_align", G_TYPE_INT,
11534               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11535               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11536               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11537               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11538           gst_buffer_unref (buf);
11539
11540           if (codec_name) {
11541             g_free (codec);
11542             codec = g_strdup (codec_name);
11543           }
11544           break;
11545         }
11546         case FOURCC_wma_:
11547         {
11548           gint len = QT_UINT32 (stsd_entry_data) - offset;
11549           const guint8 *wfex_data = stsd_entry_data + offset;
11550           const gchar *codec_name = NULL;
11551           gint version = 1;
11552           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11553           /* FIXME this should also be gst_riff_strf_auds,
11554            * but the latter one is actually missing bits-per-sample :( */
11555           typedef struct
11556           {
11557             gint16 wFormatTag;
11558             gint16 nChannels;
11559             gint32 nSamplesPerSec;
11560             gint32 nAvgBytesPerSec;
11561             gint16 nBlockAlign;
11562             gint16 wBitsPerSample;
11563             gint16 cbSize;
11564           } WAVEFORMATEX;
11565           WAVEFORMATEX wfex;
11566
11567           /* FIXME: unify with similar wavformatex parsing code above */
11568           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11569
11570           /* find wfex */
11571           while (len >= 8) {
11572             gint size;
11573
11574             if (QT_UINT32 (wfex_data) <= len)
11575               size = QT_UINT32 (wfex_data) - 8;
11576             else
11577               size = len - 8;
11578
11579             if (size < 1)
11580               /* No real data, so break out */
11581               break;
11582
11583             switch (QT_FOURCC (wfex_data + 4)) {
11584               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11585               {
11586                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11587
11588                 if (size < 8 + 18)
11589                   break;
11590
11591                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11592                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11593                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11594                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11595                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11596                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11597                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11598
11599                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11600                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11601                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11602                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11603                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11604                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11605
11606                 if (wfex.wFormatTag == 0x0161) {
11607                   codec_name = "Windows Media Audio";
11608                   version = 2;
11609                 } else if (wfex.wFormatTag == 0x0162) {
11610                   codec_name = "Windows Media Audio 9 Pro";
11611                   version = 3;
11612                 } else if (wfex.wFormatTag == 0x0163) {
11613                   codec_name = "Windows Media Audio 9 Lossless";
11614                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11615                    * fluendo codec seems to support it */
11616                   version = 4;
11617                 }
11618
11619                 gst_caps_set_simple (entry->caps,
11620                     "wmaversion", G_TYPE_INT, version,
11621                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11622                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11623                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11624                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11625
11626                 if (size > wfex.cbSize) {
11627                   GstBuffer *buf;
11628
11629                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11630                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11631                       size - wfex.cbSize);
11632                   gst_caps_set_simple (entry->caps,
11633                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11634                   gst_buffer_unref (buf);
11635                 } else {
11636                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11637                 }
11638
11639                 if (codec_name) {
11640                   g_free (codec);
11641                   codec = g_strdup (codec_name);
11642                 }
11643                 break;
11644               }
11645               default:
11646                 break;
11647             }
11648             len -= size + 8;
11649             wfex_data += size + 8;
11650           }
11651           break;
11652         }
11653         case FOURCC_opus:
11654         {
11655           const guint8 *opus_data;
11656           guint8 *channel_mapping = NULL;
11657           guint32 rate;
11658           guint8 channels;
11659           guint8 channel_mapping_family;
11660           guint8 stream_count;
11661           guint8 coupled_count;
11662           guint8 i;
11663
11664           opus_data = stsd_entry_data;
11665
11666           channels = GST_READ_UINT8 (opus_data + 45);
11667           rate = GST_READ_UINT32_LE (opus_data + 48);
11668           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11669           stream_count = GST_READ_UINT8 (opus_data + 55);
11670           coupled_count = GST_READ_UINT8 (opus_data + 56);
11671
11672           if (channels > 0) {
11673             channel_mapping = g_malloc (channels * sizeof (guint8));
11674             for (i = 0; i < channels; i++)
11675               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11676           }
11677
11678           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11679               channel_mapping_family, stream_count, coupled_count,
11680               channel_mapping);
11681           break;
11682         }
11683         default:
11684           break;
11685       }
11686
11687       if (codec) {
11688         GstStructure *s;
11689         gint bitrate = 0;
11690
11691         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11692             GST_TAG_AUDIO_CODEC, codec, NULL);
11693         g_free (codec);
11694         codec = NULL;
11695
11696         /* some bitrate info may have ended up in caps */
11697         s = gst_caps_get_structure (entry->caps, 0);
11698         gst_structure_get_int (s, "bitrate", &bitrate);
11699         if (bitrate > 0)
11700           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11701               GST_TAG_BITRATE, bitrate, NULL);
11702       }
11703
11704       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11705       if (!stream->protected) {
11706       } else {
11707         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11708           mp4v = NULL;
11709         }
11710       }
11711       if (stream->protected && fourcc == FOURCC_mp4a) {
11712         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11713           mp4a = NULL;
11714         }
11715       } else {
11716         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11717           mp4a = NULL;
11718         }
11719       }
11720
11721       wave = NULL;
11722       esds = NULL;
11723       if (mp4a) {
11724         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11725         if (wave)
11726           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11727         if (!esds)
11728           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11729       }
11730
11731
11732       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11733          16 bits is a byte-swapped wave-style codec identifier,
11734          and we can find a WAVE header internally to a 'wave' atom here.
11735          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11736          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11737          is big-endian).
11738        */
11739       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11740         if (len < offset + 20) {
11741           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11742         } else {
11743           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11744           const guint8 *data = stsd_entry_data + offset + 16;
11745           GNode *wavenode;
11746           GNode *waveheadernode;
11747
11748           wavenode = g_node_new ((guint8 *) data);
11749           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11750             const guint8 *waveheader;
11751             guint32 headerlen;
11752
11753             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11754             if (waveheadernode) {
11755               waveheader = (const guint8 *) waveheadernode->data;
11756               headerlen = QT_UINT32 (waveheader);
11757
11758               if (headerlen > 8) {
11759                 gst_riff_strf_auds *header = NULL;
11760                 GstBuffer *headerbuf;
11761                 GstBuffer *extra;
11762
11763                 waveheader += 8;
11764                 headerlen -= 8;
11765
11766                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11767                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11768
11769                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11770                         headerbuf, &header, &extra)) {
11771                   gst_caps_unref (entry->caps);
11772                   /* FIXME: Need to do something with the channel reorder map */
11773                   entry->caps =
11774                       gst_riff_create_audio_caps (header->format, NULL, header,
11775                       extra, NULL, NULL, NULL);
11776
11777                   if (extra)
11778                     gst_buffer_unref (extra);
11779                   g_free (header);
11780                 }
11781               }
11782             } else
11783               GST_DEBUG ("Didn't find waveheadernode for this codec");
11784           }
11785           g_node_destroy (wavenode);
11786         }
11787       } else if (esds) {
11788         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11789             stream->stream_tags);
11790       } else {
11791         switch (fourcc) {
11792 #if 0
11793             /* FIXME: what is in the chunk? */
11794           case FOURCC_QDMC:
11795           {
11796             gint len = QT_UINT32 (stsd_data);
11797
11798             /* seems to be always = 116 = 0x74 */
11799             break;
11800           }
11801 #endif
11802           case FOURCC_QDM2:
11803           {
11804             gint len = QT_UINT32 (stsd_entry_data);
11805
11806             if (len > 0x3C) {
11807               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11808
11809               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11810               gst_caps_set_simple (entry->caps,
11811                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11812               gst_buffer_unref (buf);
11813             }
11814             gst_caps_set_simple (entry->caps,
11815                 "samplesize", G_TYPE_INT, samplesize, NULL);
11816             break;
11817           }
11818           case FOURCC_alac:
11819           {
11820             GNode *alac, *wave = NULL;
11821
11822             /* apparently, m4a has this atom appended directly in the stsd entry,
11823              * while mov has it in a wave atom */
11824             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11825             if (alac) {
11826               /* alac now refers to stsd entry atom */
11827               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11828               if (wave)
11829                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11830               else
11831                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11832             }
11833             if (alac) {
11834               const guint8 *alac_data = alac->data;
11835               gint len = QT_UINT32 (alac->data);
11836               GstBuffer *buf;
11837
11838               if (len < 36) {
11839                 GST_DEBUG_OBJECT (qtdemux,
11840                     "discarding alac atom with unexpected len %d", len);
11841               } else {
11842                 /* codec-data contains alac atom size and prefix,
11843                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11844                 buf = gst_buffer_new_and_alloc (len);
11845                 gst_buffer_fill (buf, 0, alac->data, len);
11846                 gst_caps_set_simple (entry->caps,
11847                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11848                 gst_buffer_unref (buf);
11849
11850                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11851                 entry->n_channels = QT_UINT8 (alac_data + 21);
11852                 entry->rate = QT_UINT32 (alac_data + 32);
11853               }
11854             }
11855             gst_caps_set_simple (entry->caps,
11856                 "samplesize", G_TYPE_INT, samplesize, NULL);
11857             break;
11858           }
11859           case FOURCC_fLaC:
11860           {
11861             /* The codingname of the sample entry is 'fLaC' */
11862             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11863
11864             if (flac) {
11865               /* The 'dfLa' box is added to the sample entry to convey
11866                  initializing information for the decoder. */
11867               const GNode *dfla =
11868                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11869
11870               if (dfla) {
11871                 const guint32 len = QT_UINT32 (dfla->data);
11872
11873                 /* Must contain at least dfLa box header (12),
11874                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11875                 if (len < 50) {
11876                   GST_DEBUG_OBJECT (qtdemux,
11877                       "discarding dfla atom with unexpected len %d", len);
11878                 } else {
11879                   /* skip dfLa header to get the METADATA_BLOCKs */
11880                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11881                   const guint32 metadata_blocks_len = len - 12;
11882
11883                   gchar *stream_marker = g_strdup ("fLaC");
11884                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11885                       strlen (stream_marker));
11886
11887                   guint32 index = 0;
11888                   guint32 remainder = 0;
11889                   guint32 block_size = 0;
11890                   gboolean is_last = FALSE;
11891
11892                   GValue array = G_VALUE_INIT;
11893                   GValue value = G_VALUE_INIT;
11894
11895                   g_value_init (&array, GST_TYPE_ARRAY);
11896                   g_value_init (&value, GST_TYPE_BUFFER);
11897
11898                   gst_value_set_buffer (&value, block);
11899                   gst_value_array_append_value (&array, &value);
11900                   g_value_reset (&value);
11901
11902                   gst_buffer_unref (block);
11903
11904                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11905                    * of data, and we haven't already finished parsing */
11906                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11907                     remainder = metadata_blocks_len - index;
11908
11909                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11910                     block_size = 4 +
11911                         (metadata_blocks[index + 1] << 16) +
11912                         (metadata_blocks[index + 2] << 8) +
11913                         metadata_blocks[index + 3];
11914
11915                     /* be careful not to read off end of box */
11916                     if (block_size > remainder) {
11917                       break;
11918                     }
11919
11920                     is_last = metadata_blocks[index] >> 7;
11921
11922                     block = gst_buffer_new_and_alloc (block_size);
11923
11924                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11925                         block_size);
11926
11927                     gst_value_set_buffer (&value, block);
11928                     gst_value_array_append_value (&array, &value);
11929                     g_value_reset (&value);
11930
11931                     gst_buffer_unref (block);
11932
11933                     index += block_size;
11934                   }
11935
11936                   /* only append the metadata if we successfully read all of it */
11937                   if (is_last) {
11938                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11939                             (stream)->caps, 0), "streamheader", &array);
11940                   } else {
11941                     GST_WARNING_OBJECT (qtdemux,
11942                         "discarding all METADATA_BLOCKs due to invalid "
11943                         "block_size %d at idx %d, rem %d", block_size, index,
11944                         remainder);
11945                   }
11946
11947                   g_value_unset (&value);
11948                   g_value_unset (&array);
11949
11950                   /* The sample rate obtained from the stsd may not be accurate
11951                    * since it cannot represent rates greater than 65535Hz, so
11952                    * override that value with the sample rate from the
11953                    * METADATA_BLOCK_STREAMINFO block */
11954                   CUR_STREAM (stream)->rate =
11955                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11956                 }
11957               }
11958             }
11959             break;
11960           }
11961           case FOURCC_sawb:
11962             /* Fallthrough! */
11963             amrwb = TRUE;
11964           case FOURCC_samr:
11965           {
11966             gint len = QT_UINT32 (stsd_entry_data);
11967
11968             if (len > 0x24) {
11969               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11970               guint bitrate;
11971
11972               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11973
11974               /* If we have enough data, let's try to get the 'damr' atom. See
11975                * the 3GPP container spec (26.244) for more details. */
11976               if ((len - 0x34) > 8 &&
11977                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11978                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11979                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11980               }
11981
11982               gst_caps_set_simple (entry->caps,
11983                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11984               gst_buffer_unref (buf);
11985             }
11986             break;
11987           }
11988           case FOURCC_mp4a:
11989           {
11990             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11991             gint len = QT_UINT32 (stsd_entry_data);
11992
11993             if (len >= 34) {
11994               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11995
11996               if (sound_version == 1) {
11997                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11998                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11999                 guint8 codec_data[2];
12000                 GstBuffer *buf;
12001                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12002
12003                 gint sample_rate_index =
12004                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12005
12006                 /* build AAC codec data */
12007                 codec_data[0] = profile << 3;
12008                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12009                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12010                 codec_data[1] |= (channels & 0xF) << 3;
12011
12012                 buf = gst_buffer_new_and_alloc (2);
12013                 gst_buffer_fill (buf, 0, codec_data, 2);
12014                 gst_caps_set_simple (entry->caps,
12015                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12016                 gst_buffer_unref (buf);
12017               }
12018             }
12019             break;
12020           }
12021           default:
12022             GST_INFO_OBJECT (qtdemux,
12023                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12024             break;
12025         }
12026       }
12027       GST_INFO_OBJECT (qtdemux,
12028           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12029           GST_FOURCC_ARGS (fourcc), entry->caps);
12030
12031     } else if (stream->subtype == FOURCC_strm) {
12032       if (fourcc == FOURCC_rtsp) {
12033         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12034       } else {
12035         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12036             GST_FOURCC_ARGS (fourcc));
12037         goto unknown_stream;
12038       }
12039       entry->sampled = TRUE;
12040     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12041         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
12042
12043       entry->sampled = TRUE;
12044       entry->sparse = TRUE;
12045
12046       entry->caps =
12047           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12048           &codec);
12049       if (codec) {
12050         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12051             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12052         g_free (codec);
12053         codec = NULL;
12054       }
12055
12056       /* hunt for sort-of codec data */
12057       switch (fourcc) {
12058         case FOURCC_mp4s:
12059         {
12060           GNode *mp4s = NULL;
12061           GNode *esds = NULL;
12062
12063           /* look for palette in a stsd->mp4s->esds sub-atom */
12064           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12065           if (mp4s)
12066             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12067           if (esds == NULL) {
12068             /* Invalid STSD */
12069             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12070             break;
12071           }
12072
12073           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12074               stream->stream_tags);
12075           break;
12076         }
12077         default:
12078           GST_INFO_OBJECT (qtdemux,
12079               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12080           break;
12081       }
12082       GST_INFO_OBJECT (qtdemux,
12083           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12084           GST_FOURCC_ARGS (fourcc), entry->caps);
12085     } else {
12086       /* everything in 1 sample */
12087       entry->sampled = TRUE;
12088
12089       entry->caps =
12090           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12091           &codec);
12092
12093       if (entry->caps == NULL)
12094         goto unknown_stream;
12095
12096       if (codec) {
12097         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12098             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12099         g_free (codec);
12100         codec = NULL;
12101       }
12102     }
12103
12104     /* promote to sampled format */
12105     if (entry->fourcc == FOURCC_samr) {
12106       /* force mono 8000 Hz for AMR */
12107       entry->sampled = TRUE;
12108       entry->n_channels = 1;
12109       entry->rate = 8000;
12110     } else if (entry->fourcc == FOURCC_sawb) {
12111       /* force mono 16000 Hz for AMR-WB */
12112       entry->sampled = TRUE;
12113       entry->n_channels = 1;
12114       entry->rate = 16000;
12115     } else if (entry->fourcc == FOURCC_mp4a) {
12116       entry->sampled = TRUE;
12117     }
12118
12119
12120     stsd_entry_data += len;
12121     remaining_stsd_len -= len;
12122
12123   }
12124
12125   /* collect sample information */
12126   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12127     goto samples_failed;
12128
12129   if (qtdemux->fragmented) {
12130     guint64 offset;
12131
12132     /* need all moov samples as basis; probably not many if any at all */
12133     /* prevent moof parsing taking of at this time */
12134     offset = qtdemux->moof_offset;
12135     qtdemux->moof_offset = 0;
12136     if (stream->n_samples &&
12137         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12138       qtdemux->moof_offset = offset;
12139       goto samples_failed;
12140     }
12141     qtdemux->moof_offset = 0;
12142     /* movie duration more reliable in this case (e.g. mehd) */
12143     if (qtdemux->segment.duration &&
12144         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12145       stream->duration =
12146           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12147   }
12148
12149   /* configure segments */
12150   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12151     goto segments_failed;
12152
12153   /* add some language tag, if useful */
12154   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12155       strcmp (stream->lang_id, "und")) {
12156     const gchar *lang_code;
12157
12158     /* convert ISO 639-2 code to ISO 639-1 */
12159     lang_code = gst_tag_get_language_code (stream->lang_id);
12160     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12161         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12162   }
12163
12164   /* Check for UDTA tags */
12165   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12166     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12167   }
12168
12169   /* now we are ready to add the stream */
12170   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
12171     goto too_many_streams;
12172
12173   if (!qtdemux->got_moov) {
12174     qtdemux->streams[qtdemux->n_streams] = stream;
12175     qtdemux->n_streams++;
12176     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12177   }
12178
12179   return TRUE;
12180
12181 /* ERRORS */
12182 skip_track:
12183   {
12184     GST_INFO_OBJECT (qtdemux, "skip disabled track");
12185     if (new_stream)
12186       gst_qtdemux_stream_free (qtdemux, stream);
12187     return TRUE;
12188   }
12189 corrupt_file:
12190   {
12191     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12192         (_("This file is corrupt and cannot be played.")), (NULL));
12193     if (new_stream)
12194       gst_qtdemux_stream_free (qtdemux, stream);
12195     return FALSE;
12196   }
12197 error_encrypted:
12198   {
12199     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12200     if (new_stream)
12201       gst_qtdemux_stream_free (qtdemux, stream);
12202     return FALSE;
12203   }
12204 samples_failed:
12205 segments_failed:
12206   {
12207     /* we posted an error already */
12208     /* free stbl sub-atoms */
12209     gst_qtdemux_stbl_free (stream);
12210     if (new_stream)
12211       gst_qtdemux_stream_free (qtdemux, stream);
12212     return FALSE;
12213   }
12214 existing_stream:
12215   {
12216     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12217         track_id);
12218     if (new_stream)
12219       gst_qtdemux_stream_free (qtdemux, stream);
12220     return TRUE;
12221   }
12222 unknown_stream:
12223   {
12224     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12225         GST_FOURCC_ARGS (stream->subtype));
12226     if (new_stream)
12227       gst_qtdemux_stream_free (qtdemux, stream);
12228     return TRUE;
12229   }
12230 too_many_streams:
12231   {
12232     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
12233         (_("This file contains too many streams. Only playing first %d"),
12234             GST_QTDEMUX_MAX_STREAMS), (NULL));
12235     return TRUE;
12236   }
12237 }
12238
12239 /* If we can estimate the overall bitrate, and don't have information about the
12240  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12241  * the overall bitrate minus the sum of the bitrates of all other streams. This
12242  * should be useful for the common case where we have one audio and one video
12243  * stream and can estimate the bitrate of one, but not the other. */
12244 static void
12245 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12246 {
12247   QtDemuxStream *stream = NULL;
12248   gint64 size, sys_bitrate, sum_bitrate = 0;
12249   GstClockTime duration;
12250   gint i;
12251   guint bitrate;
12252
12253   if (qtdemux->fragmented)
12254     return;
12255
12256   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12257
12258   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12259       || size <= 0) {
12260     GST_DEBUG_OBJECT (qtdemux,
12261         "Size in bytes of the stream not known - bailing");
12262     return;
12263   }
12264
12265   /* Subtract the header size */
12266   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12267       size, qtdemux->header_size);
12268
12269   if (size < qtdemux->header_size)
12270     return;
12271
12272   size = size - qtdemux->header_size;
12273
12274   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12275     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12276     return;
12277   }
12278
12279   for (i = 0; i < qtdemux->n_streams; i++) {
12280     switch (qtdemux->streams[i]->subtype) {
12281       case FOURCC_soun:
12282       case FOURCC_vide:
12283         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12284             CUR_STREAM (qtdemux->streams[i])->caps);
12285         /* retrieve bitrate, prefer avg then max */
12286         bitrate = 0;
12287         if (qtdemux->streams[i]->stream_tags) {
12288           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
12289               GST_TAG_MAXIMUM_BITRATE, &bitrate);
12290           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12291           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
12292               GST_TAG_NOMINAL_BITRATE, &bitrate);
12293           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12294           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
12295               GST_TAG_BITRATE, &bitrate);
12296           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12297         }
12298         if (bitrate)
12299           sum_bitrate += bitrate;
12300         else {
12301           if (stream) {
12302             GST_DEBUG_OBJECT (qtdemux,
12303                 ">1 stream with unknown bitrate - bailing");
12304             return;
12305           } else
12306             stream = qtdemux->streams[i];
12307         }
12308
12309       default:
12310         /* For other subtypes, we assume no significant impact on bitrate */
12311         break;
12312     }
12313   }
12314
12315   if (!stream) {
12316     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12317     return;
12318   }
12319
12320   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12321
12322   if (sys_bitrate < sum_bitrate) {
12323     /* This can happen, since sum_bitrate might be derived from maximum
12324      * bitrates and not average bitrates */
12325     GST_DEBUG_OBJECT (qtdemux,
12326         "System bitrate less than sum bitrate - bailing");
12327     return;
12328   }
12329
12330   bitrate = sys_bitrate - sum_bitrate;
12331   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12332       ", Stream bitrate = %u", sys_bitrate, bitrate);
12333
12334   if (!stream->stream_tags)
12335     stream->stream_tags = gst_tag_list_new_empty ();
12336   else
12337     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12338
12339   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12340       GST_TAG_BITRATE, bitrate, NULL);
12341 }
12342
12343 static GstFlowReturn
12344 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12345 {
12346   gint i;
12347   GstFlowReturn ret = GST_FLOW_OK;
12348
12349   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12350
12351   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
12352     QtDemuxStream *stream = qtdemux->streams[i];
12353     guint32 sample_num = 0;
12354
12355     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
12356         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12357
12358     if (qtdemux->fragmented) {
12359       /* need all moov samples first */
12360       GST_OBJECT_LOCK (qtdemux);
12361       while (stream->n_samples == 0)
12362         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12363           break;
12364       GST_OBJECT_UNLOCK (qtdemux);
12365     } else {
12366       /* discard any stray moof */
12367       qtdemux->moof_offset = 0;
12368     }
12369
12370     /* prepare braking */
12371     if (ret != GST_FLOW_ERROR)
12372       ret = GST_FLOW_OK;
12373
12374     /* in pull mode, we should have parsed some sample info by now;
12375      * and quite some code will not handle no samples.
12376      * in push mode, we'll just have to deal with it */
12377     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12378       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12379       gst_qtdemux_remove_stream (qtdemux, i);
12380       i--;
12381       continue;
12382     }
12383
12384     /* parse the initial sample for use in setting the frame rate cap */
12385     while (sample_num == 0 && sample_num < stream->n_samples) {
12386       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12387         break;
12388       ++sample_num;
12389     }
12390     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
12391       stream->first_duration = stream->samples[0].duration;
12392       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
12393           stream->track_id, stream->first_duration);
12394     }
12395   }
12396
12397   return ret;
12398 }
12399
12400 static GstFlowReturn
12401 qtdemux_expose_streams (GstQTDemux * qtdemux)
12402 {
12403   gint i;
12404   GSList *oldpads = NULL;
12405   GSList *iter;
12406
12407   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12408
12409   for (i = 0; i < qtdemux->n_streams; i++) {
12410     QtDemuxStream *stream = qtdemux->streams[i];
12411     GstPad *oldpad = stream->pad;
12412     GstTagList *list;
12413
12414     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
12415         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12416
12417     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
12418         stream->track_id == qtdemux->chapters_track_id) {
12419       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12420          so that it doesn't look like a subtitle track */
12421       gst_qtdemux_remove_stream (qtdemux, i);
12422       i--;
12423       continue;
12424     }
12425
12426     /* now we have all info and can expose */
12427     list = stream->stream_tags;
12428     stream->stream_tags = NULL;
12429     if (oldpad)
12430       oldpads = g_slist_prepend (oldpads, oldpad);
12431     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12432       return GST_FLOW_ERROR;
12433   }
12434
12435   gst_qtdemux_guess_bitrate (qtdemux);
12436
12437   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12438
12439   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
12440     GstPad *oldpad = iter->data;
12441     GstEvent *event;
12442
12443     event = gst_event_new_eos ();
12444     if (qtdemux->segment_seqnum)
12445       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12446
12447     gst_pad_push_event (oldpad, event);
12448     gst_pad_set_active (oldpad, FALSE);
12449     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
12450     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
12451     gst_object_unref (oldpad);
12452   }
12453
12454   /* check if we should post a redirect in case there is a single trak
12455    * and it is a redirecting trak */
12456   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
12457     GstMessage *m;
12458
12459     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12460         "an external content");
12461     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12462         gst_structure_new ("redirect",
12463             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
12464             NULL));
12465     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12466     qtdemux->posted_redirect = TRUE;
12467   }
12468
12469   for (i = 0; i < qtdemux->n_streams; i++) {
12470     QtDemuxStream *stream = qtdemux->streams[i];
12471
12472     qtdemux_do_allocation (qtdemux, stream);
12473   }
12474
12475   qtdemux->exposed = TRUE;
12476   return GST_FLOW_OK;
12477 }
12478
12479 /* check if major or compatible brand is 3GP */
12480 static inline gboolean
12481 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12482 {
12483   if (major) {
12484     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12485         FOURCC_3g__);
12486   } else if (qtdemux->comp_brands != NULL) {
12487     GstMapInfo map;
12488     guint8 *data;
12489     gsize size;
12490     gboolean res = FALSE;
12491
12492     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12493     data = map.data;
12494     size = map.size;
12495     while (size >= 4) {
12496       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12497           FOURCC_3g__);
12498       data += 4;
12499       size -= 4;
12500     }
12501     gst_buffer_unmap (qtdemux->comp_brands, &map);
12502     return res;
12503   } else {
12504     return FALSE;
12505   }
12506 }
12507
12508 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12509 static inline gboolean
12510 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12511 {
12512   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12513       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12514       || fourcc == FOURCC_albm;
12515 }
12516
12517 static void
12518 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12519     const char *tag, const char *dummy, GNode * node)
12520 {
12521   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12522   int offset;
12523   char *name;
12524   gchar *data;
12525   gdouble longitude, latitude, altitude;
12526   gint len;
12527
12528   len = QT_UINT32 (node->data);
12529   if (len <= 14)
12530     goto short_read;
12531
12532   data = node->data;
12533   offset = 14;
12534
12535   /* TODO: language code skipped */
12536
12537   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12538
12539   if (!name) {
12540     /* do not alarm in trivial case, but bail out otherwise */
12541     if (*(data + offset) != 0) {
12542       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12543           "giving up", tag);
12544     }
12545   } else {
12546     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12547         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12548     offset += strlen (name);
12549     g_free (name);
12550   }
12551
12552   if (len < offset + 2 + 4 + 4 + 4)
12553     goto short_read;
12554
12555   /* +1 +1 = skip null-terminator and location role byte */
12556   offset += 1 + 1;
12557   /* table in spec says unsigned, semantics say negative has meaning ... */
12558   longitude = QT_SFP32 (data + offset);
12559
12560   offset += 4;
12561   latitude = QT_SFP32 (data + offset);
12562
12563   offset += 4;
12564   altitude = QT_SFP32 (data + offset);
12565
12566   /* one invalid means all are invalid */
12567   if (longitude >= -180.0 && longitude <= 180.0 &&
12568       latitude >= -90.0 && latitude <= 90.0) {
12569     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12570         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12571         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12572         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12573   }
12574
12575   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12576
12577   return;
12578
12579   /* ERRORS */
12580 short_read:
12581   {
12582     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12583     return;
12584   }
12585 }
12586
12587
12588 static void
12589 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12590     const char *tag, const char *dummy, GNode * node)
12591 {
12592   guint16 y;
12593   GDate *date;
12594   gint len;
12595
12596   len = QT_UINT32 (node->data);
12597   if (len < 14)
12598     return;
12599
12600   y = QT_UINT16 ((guint8 *) node->data + 12);
12601   if (y == 0) {
12602     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12603     return;
12604   }
12605   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12606
12607   date = g_date_new_dmy (1, 1, y);
12608   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12609   g_date_free (date);
12610 }
12611
12612 static void
12613 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12614     const char *tag, const char *dummy, GNode * node)
12615 {
12616   int offset;
12617   char *tag_str = NULL;
12618   guint8 *entity;
12619   guint16 table;
12620   gint len;
12621
12622   len = QT_UINT32 (node->data);
12623   if (len <= 20)
12624     goto short_read;
12625
12626   offset = 12;
12627   entity = (guint8 *) node->data + offset;
12628   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12629     GST_DEBUG_OBJECT (qtdemux,
12630         "classification info: %c%c%c%c invalid classification entity",
12631         entity[0], entity[1], entity[2], entity[3]);
12632     return;
12633   }
12634
12635   offset += 4;
12636   table = QT_UINT16 ((guint8 *) node->data + offset);
12637
12638   /* Language code skipped */
12639
12640   offset += 4;
12641
12642   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12643    * XXXX: classification entity, fixed length 4 chars.
12644    * Y[YYYY]: classification table, max 5 chars.
12645    */
12646   tag_str = g_strdup_printf ("----://%u/%s",
12647       table, (char *) node->data + offset);
12648
12649   /* memcpy To be sure we're preserving byte order */
12650   memcpy (tag_str, entity, 4);
12651   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12652
12653   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12654
12655   g_free (tag_str);
12656
12657   return;
12658
12659   /* ERRORS */
12660 short_read:
12661   {
12662     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12663     return;
12664   }
12665 }
12666
12667 static gboolean
12668 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12669     const char *tag, const char *dummy, GNode * node)
12670 {
12671   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12672   GNode *data;
12673   char *s;
12674   int len;
12675   guint32 type;
12676   int offset;
12677   gboolean ret = TRUE;
12678   const gchar *charset = NULL;
12679
12680   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12681   if (data) {
12682     len = QT_UINT32 (data->data);
12683     type = QT_UINT32 ((guint8 *) data->data + 8);
12684     if (type == 0x00000001 && len > 16) {
12685       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12686           env_vars);
12687       if (s) {
12688         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12689         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12690         g_free (s);
12691       } else {
12692         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12693       }
12694     }
12695   } else {
12696     len = QT_UINT32 (node->data);
12697     type = QT_UINT32 ((guint8 *) node->data + 4);
12698     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12699       gint str_len;
12700       gint lang_code;
12701
12702       /* Type starts with the (C) symbol, so the next data is a list
12703        * of (string size(16), language code(16), string) */
12704
12705       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12706       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12707
12708       /* the string + fourcc + size + 2 16bit fields,
12709        * means that there are more tags in this atom */
12710       if (len > str_len + 8 + 4) {
12711         /* TODO how to represent the same tag in different languages? */
12712         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12713             "text alternatives, reading only first one");
12714       }
12715
12716       offset = 12;
12717       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12718       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12719
12720       if (lang_code < 0x800) {  /* MAC encoded string */
12721         charset = "mac";
12722       }
12723     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12724             QT_FOURCC ((guint8 *) node->data + 4))) {
12725       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12726
12727       /* we go for 3GP style encoding if major brands claims so,
12728        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12729       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12730           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12731               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12732         offset = 14;
12733         /* 16-bit Language code is ignored here as well */
12734         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12735       } else {
12736         goto normal;
12737       }
12738     } else {
12739     normal:
12740       offset = 8;
12741       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12742       ret = FALSE;              /* may have to fallback */
12743     }
12744     if (charset) {
12745       GError *err = NULL;
12746
12747       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12748           charset, NULL, NULL, &err);
12749       if (err) {
12750         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12751             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12752             err->message);
12753         g_error_free (err);
12754       }
12755     } else {
12756       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12757           len - offset, env_vars);
12758     }
12759     if (s) {
12760       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12761       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12762       g_free (s);
12763       ret = TRUE;
12764     } else {
12765       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12766     }
12767   }
12768   return ret;
12769 }
12770
12771 static void
12772 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12773     const char *tag, const char *dummy, GNode * node)
12774 {
12775   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12776 }
12777
12778 static void
12779 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12780     const char *tag, const char *dummy, GNode * node)
12781 {
12782   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12783   guint8 *data;
12784   char *s, *t, *k = NULL;
12785   int len;
12786   int offset;
12787   int count;
12788
12789   /* first try normal string tag if major brand not 3GP */
12790   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12791     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12792       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12793        * let's try it 3gpp way after minor safety check */
12794       data = node->data;
12795       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12796         return;
12797     } else
12798       return;
12799   }
12800
12801   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12802
12803   data = node->data;
12804
12805   len = QT_UINT32 (data);
12806   if (len < 15)
12807     goto short_read;
12808
12809   count = QT_UINT8 (data + 14);
12810   offset = 15;
12811   for (; count; count--) {
12812     gint slen;
12813
12814     if (offset + 1 > len)
12815       goto short_read;
12816     slen = QT_UINT8 (data + offset);
12817     offset += 1;
12818     if (offset + slen > len)
12819       goto short_read;
12820     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12821         slen, env_vars);
12822     if (s) {
12823       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12824       if (k) {
12825         t = g_strjoin (",", k, s, NULL);
12826         g_free (s);
12827         g_free (k);
12828         k = t;
12829       } else {
12830         k = s;
12831       }
12832     } else {
12833       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12834     }
12835     offset += slen;
12836   }
12837
12838 done:
12839   if (k) {
12840     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12841     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12842   }
12843   g_free (k);
12844
12845   return;
12846
12847   /* ERRORS */
12848 short_read:
12849   {
12850     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12851     goto done;
12852   }
12853 }
12854
12855 static void
12856 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12857     const char *tag1, const char *tag2, GNode * node)
12858 {
12859   GNode *data;
12860   int len;
12861   int type;
12862   int n1, n2;
12863
12864   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12865   if (data) {
12866     len = QT_UINT32 (data->data);
12867     type = QT_UINT32 ((guint8 *) data->data + 8);
12868     if (type == 0x00000000 && len >= 22) {
12869       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12870       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12871       if (n1 > 0) {
12872         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12873         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12874       }
12875       if (n2 > 0) {
12876         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12877         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12878       }
12879     }
12880   }
12881 }
12882
12883 static void
12884 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12885     const char *tag1, const char *dummy, GNode * node)
12886 {
12887   GNode *data;
12888   int len;
12889   int type;
12890   int n1;
12891
12892   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12893   if (data) {
12894     len = QT_UINT32 (data->data);
12895     type = QT_UINT32 ((guint8 *) data->data + 8);
12896     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12897     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12898     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12899       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12900       if (n1) {
12901         /* do not add bpm=0 */
12902         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12903         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12904             NULL);
12905       }
12906     }
12907   }
12908 }
12909
12910 static void
12911 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12912     const char *tag1, const char *dummy, GNode * node)
12913 {
12914   GNode *data;
12915   int len;
12916   int type;
12917   guint32 num;
12918
12919   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12920   if (data) {
12921     len = QT_UINT32 (data->data);
12922     type = QT_UINT32 ((guint8 *) data->data + 8);
12923     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12924     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12925     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12926       num = QT_UINT32 ((guint8 *) data->data + 16);
12927       if (num) {
12928         /* do not add num=0 */
12929         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12930         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12931       }
12932     }
12933   }
12934 }
12935
12936 static void
12937 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12938     const char *tag1, const char *dummy, GNode * node)
12939 {
12940   GNode *data;
12941   int len;
12942   int type;
12943   GstSample *sample;
12944
12945   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12946   if (data) {
12947     len = QT_UINT32 (data->data);
12948     type = QT_UINT32 ((guint8 *) data->data + 8);
12949     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12950     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12951       GstTagImageType image_type;
12952
12953       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12954         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12955       else
12956         image_type = GST_TAG_IMAGE_TYPE_NONE;
12957
12958       if ((sample =
12959               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12960                   len - 16, image_type))) {
12961         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12962         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12963         gst_sample_unref (sample);
12964       }
12965     }
12966   }
12967 }
12968
12969 static void
12970 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12971     const char *tag, const char *dummy, GNode * node)
12972 {
12973   GNode *data;
12974   char *s;
12975   int len;
12976   int type;
12977
12978   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12979   if (data) {
12980     len = QT_UINT32 (data->data);
12981     type = QT_UINT32 ((guint8 *) data->data + 8);
12982     if (type == 0x00000001 && len > 16) {
12983       guint y, m = 1, d = 1;
12984       gint ret;
12985
12986       s = g_strndup ((char *) data->data + 16, len - 16);
12987       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12988       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12989       if (ret >= 1 && y > 1500 && y < 3000) {
12990         GDate *date;
12991
12992         date = g_date_new_dmy (d, m, y);
12993         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12994         g_date_free (date);
12995       } else {
12996         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12997       }
12998       g_free (s);
12999     }
13000   }
13001 }
13002
13003 static void
13004 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13005     const char *tag, const char *dummy, GNode * node)
13006 {
13007   GNode *data;
13008
13009   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13010
13011   /* re-route to normal string tag if major brand says so
13012    * or no data atom and compatible brand suggests so */
13013   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13014       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13015     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13016     return;
13017   }
13018
13019   if (data) {
13020     guint len, type, n;
13021
13022     len = QT_UINT32 (data->data);
13023     type = QT_UINT32 ((guint8 *) data->data + 8);
13024     if (type == 0x00000000 && len >= 18) {
13025       n = QT_UINT16 ((guint8 *) data->data + 16);
13026       if (n > 0) {
13027         const gchar *genre;
13028
13029         genre = gst_tag_id3_genre_get (n - 1);
13030         if (genre != NULL) {
13031           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13032           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13033         }
13034       }
13035     }
13036   }
13037 }
13038
13039 static void
13040 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13041     const gchar * tag, guint8 * data, guint32 datasize)
13042 {
13043   gdouble value;
13044   gchar *datacopy;
13045
13046   /* make a copy to have \0 at the end */
13047   datacopy = g_strndup ((gchar *) data, datasize);
13048
13049   /* convert the str to double */
13050   if (sscanf (datacopy, "%lf", &value) == 1) {
13051     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13052     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13053   } else {
13054     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13055         datacopy);
13056   }
13057   g_free (datacopy);
13058 }
13059
13060
13061 static void
13062 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13063     const char *tag, const char *tag_bis, GNode * node)
13064 {
13065   GNode *mean;
13066   GNode *name;
13067   GNode *data;
13068   guint32 meansize;
13069   guint32 namesize;
13070   guint32 datatype;
13071   guint32 datasize;
13072   const gchar *meanstr;
13073   const gchar *namestr;
13074
13075   /* checking the whole ---- atom size for consistency */
13076   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13077     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13078     return;
13079   }
13080
13081   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13082   if (!mean) {
13083     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13084     return;
13085   }
13086
13087   meansize = QT_UINT32 (mean->data);
13088   if (meansize <= 12) {
13089     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13090     return;
13091   }
13092   meanstr = ((gchar *) mean->data) + 12;
13093   meansize -= 12;
13094
13095   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13096   if (!name) {
13097     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13098     return;
13099   }
13100
13101   namesize = QT_UINT32 (name->data);
13102   if (namesize <= 12) {
13103     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13104     return;
13105   }
13106   namestr = ((gchar *) name->data) + 12;
13107   namesize -= 12;
13108
13109   /*
13110    * Data atom is:
13111    * uint32 - size
13112    * uint32 - name
13113    * uint8  - version
13114    * uint24 - data type
13115    * uint32 - all 0
13116    * rest   - the data
13117    */
13118   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13119   if (!data) {
13120     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13121     return;
13122   }
13123   datasize = QT_UINT32 (data->data);
13124   if (datasize <= 16) {
13125     GST_WARNING_OBJECT (demux, "Data atom too small");
13126     return;
13127   }
13128   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13129
13130   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13131       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13132     static const struct
13133     {
13134       const gchar name[28];
13135       const gchar tag[28];
13136     } tags[] = {
13137       {
13138       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13139       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13140       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13141       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13142       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13143       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13144       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13145       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13146     };
13147     int i;
13148
13149     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13150       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13151         switch (gst_tag_get_type (tags[i].tag)) {
13152           case G_TYPE_DOUBLE:
13153             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13154                 ((guint8 *) data->data) + 16, datasize - 16);
13155             break;
13156           case G_TYPE_STRING:
13157             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13158             break;
13159           default:
13160             /* not reached */
13161             break;
13162         }
13163         break;
13164       }
13165     }
13166     if (i == G_N_ELEMENTS (tags))
13167       goto unknown_tag;
13168   } else {
13169     goto unknown_tag;
13170   }
13171
13172   return;
13173
13174 /* errors */
13175 unknown_tag:
13176 #ifndef GST_DISABLE_GST_DEBUG
13177   {
13178     gchar *namestr_dbg;
13179     gchar *meanstr_dbg;
13180
13181     meanstr_dbg = g_strndup (meanstr, meansize);
13182     namestr_dbg = g_strndup (namestr, namesize);
13183
13184     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13185         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13186
13187     g_free (namestr_dbg);
13188     g_free (meanstr_dbg);
13189   }
13190 #endif
13191   return;
13192 }
13193
13194 static void
13195 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13196     const char *tag_bis, GNode * node)
13197 {
13198   guint8 *data;
13199   GstBuffer *buf;
13200   guint len;
13201   GstTagList *id32_taglist = NULL;
13202
13203   GST_LOG_OBJECT (demux, "parsing ID32");
13204
13205   data = node->data;
13206   len = GST_READ_UINT32_BE (data);
13207
13208   /* need at least full box and language tag */
13209   if (len < 12 + 2)
13210     return;
13211
13212   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13213   gst_buffer_fill (buf, 0, data + 14, len - 14);
13214
13215   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13216   if (id32_taglist) {
13217     GST_LOG_OBJECT (demux, "parsing ok");
13218     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13219     gst_tag_list_unref (id32_taglist);
13220   } else {
13221     GST_LOG_OBJECT (demux, "parsing failed");
13222   }
13223
13224   gst_buffer_unref (buf);
13225 }
13226
13227 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13228     const char *tag, const char *tag_bis, GNode * node);
13229
13230 /* unmapped tags
13231 FOURCC_pcst -> if media is a podcast -> bool
13232 FOURCC_cpil -> if media is part of a compilation -> bool
13233 FOURCC_pgap -> if media is part of a gapless context -> bool
13234 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13235 */
13236
13237 static const struct
13238 {
13239   guint32 fourcc;
13240   const gchar *gst_tag;
13241   const gchar *gst_tag_bis;
13242   const GstQTDemuxAddTagFunc func;
13243 } add_funcs[] = {
13244   {
13245   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13246   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13247   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13248   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13249   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13250   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13251   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13252   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13253   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13254   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13255   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13256   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13257   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13258   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13259   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13260   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13261   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13262   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13263   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13264   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13265   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13266   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13267   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13268         qtdemux_tag_add_num}, {
13269   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13270         qtdemux_tag_add_num}, {
13271   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13272   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13273   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13274   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13275   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13276   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13277   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13278   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13279   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13280   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13281   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13282   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13283   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13284   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13285   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13286   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13287   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13288   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13289         qtdemux_tag_add_classification}, {
13290   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13291   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13292   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13293
13294     /* This is a special case, some tags are stored in this
13295      * 'reverse dns naming', according to:
13296      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13297      * bug #614471
13298      */
13299   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13300     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13301   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13302 };
13303
13304 struct _GstQtDemuxTagList
13305 {
13306   GstQTDemux *demux;
13307   GstTagList *taglist;
13308 };
13309 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13310
13311 static void
13312 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13313 {
13314   gint len;
13315   guint8 *data;
13316   GstBuffer *buf;
13317   gchar *media_type;
13318   const gchar *style;
13319   GstSample *sample;
13320   GstStructure *s;
13321   guint i;
13322   guint8 ndata[4];
13323   GstQTDemux *demux = qtdemuxtaglist->demux;
13324   GstTagList *taglist = qtdemuxtaglist->taglist;
13325
13326   data = node->data;
13327   len = QT_UINT32 (data);
13328   buf = gst_buffer_new_and_alloc (len);
13329   gst_buffer_fill (buf, 0, data, len);
13330
13331   /* heuristic to determine style of tag */
13332   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13333       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13334     style = "itunes";
13335   else if (demux->major_brand == FOURCC_qt__)
13336     style = "quicktime";
13337   /* fall back to assuming iso/3gp tag style */
13338   else
13339     style = "iso";
13340
13341   /* santize the name for the caps. */
13342   for (i = 0; i < 4; i++) {
13343     guint8 d = data[4 + i];
13344     if (g_ascii_isalnum (d))
13345       ndata[i] = g_ascii_tolower (d);
13346     else
13347       ndata[i] = '_';
13348   }
13349
13350   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13351       ndata[0], ndata[1], ndata[2], ndata[3]);
13352   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13353
13354   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13355   sample = gst_sample_new (buf, NULL, NULL, s);
13356   gst_buffer_unref (buf);
13357   g_free (media_type);
13358
13359   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13360       len, s);
13361
13362   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13363       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13364
13365   gst_sample_unref (sample);
13366 }
13367
13368 static void
13369 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13370 {
13371   GNode *meta;
13372   GNode *ilst;
13373   GNode *xmp_;
13374   GNode *node;
13375   gint i;
13376   GstQtDemuxTagList demuxtaglist;
13377
13378   demuxtaglist.demux = qtdemux;
13379   demuxtaglist.taglist = taglist;
13380
13381   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13382   if (meta != NULL) {
13383     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13384     if (ilst == NULL) {
13385       GST_LOG_OBJECT (qtdemux, "no ilst");
13386       return;
13387     }
13388   } else {
13389     ilst = udta;
13390     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13391   }
13392
13393   i = 0;
13394   while (i < G_N_ELEMENTS (add_funcs)) {
13395     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13396     if (node) {
13397       gint len;
13398
13399       len = QT_UINT32 (node->data);
13400       if (len < 12) {
13401         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13402             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13403       } else {
13404         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13405             add_funcs[i].gst_tag_bis, node);
13406       }
13407       g_node_destroy (node);
13408     } else {
13409       i++;
13410     }
13411   }
13412
13413   /* parsed nodes have been removed, pass along remainder as blob */
13414   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13415       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13416
13417   /* parse up XMP_ node if existing */
13418   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13419   if (xmp_ != NULL) {
13420     GstBuffer *buf;
13421     GstTagList *xmptaglist;
13422
13423     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13424         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13425     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13426     gst_buffer_unref (buf);
13427
13428     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13429   } else {
13430     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13431   }
13432 }
13433
13434 typedef struct
13435 {
13436   GstStructure *structure;      /* helper for sort function */
13437   gchar *location;
13438   guint min_req_bitrate;
13439   guint min_req_qt_version;
13440 } GstQtReference;
13441
13442 static gint
13443 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13444 {
13445   GstQtReference *ref_a = (GstQtReference *) a;
13446   GstQtReference *ref_b = (GstQtReference *) b;
13447
13448   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13449     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13450
13451   /* known bitrates go before unknown; higher bitrates go first */
13452   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13453 }
13454
13455 /* sort the redirects and post a message for the application.
13456  */
13457 static void
13458 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13459 {
13460   GstQtReference *best;
13461   GstStructure *s;
13462   GstMessage *msg;
13463   GValue list_val = { 0, };
13464   GList *l;
13465
13466   g_assert (references != NULL);
13467
13468   references = g_list_sort (references, qtdemux_redirects_sort_func);
13469
13470   best = (GstQtReference *) references->data;
13471
13472   g_value_init (&list_val, GST_TYPE_LIST);
13473
13474   for (l = references; l != NULL; l = l->next) {
13475     GstQtReference *ref = (GstQtReference *) l->data;
13476     GValue struct_val = { 0, };
13477
13478     ref->structure = gst_structure_new ("redirect",
13479         "new-location", G_TYPE_STRING, ref->location, NULL);
13480
13481     if (ref->min_req_bitrate > 0) {
13482       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13483           ref->min_req_bitrate, NULL);
13484     }
13485
13486     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13487     g_value_set_boxed (&struct_val, ref->structure);
13488     gst_value_list_append_value (&list_val, &struct_val);
13489     g_value_unset (&struct_val);
13490     /* don't free anything here yet, since we need best->structure below */
13491   }
13492
13493   g_assert (best != NULL);
13494   s = gst_structure_copy (best->structure);
13495
13496   if (g_list_length (references) > 1) {
13497     gst_structure_set_value (s, "locations", &list_val);
13498   }
13499
13500   g_value_unset (&list_val);
13501
13502   for (l = references; l != NULL; l = l->next) {
13503     GstQtReference *ref = (GstQtReference *) l->data;
13504
13505     gst_structure_free (ref->structure);
13506     g_free (ref->location);
13507     g_free (ref);
13508   }
13509   g_list_free (references);
13510
13511   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13512   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13513   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13514   qtdemux->posted_redirect = TRUE;
13515 }
13516
13517 /* look for redirect nodes, collect all redirect information and
13518  * process it.
13519  */
13520 static gboolean
13521 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13522 {
13523   GNode *rmra, *rmda, *rdrf;
13524
13525   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13526   if (rmra) {
13527     GList *redirects = NULL;
13528
13529     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13530     while (rmda) {
13531       GstQtReference ref = { NULL, NULL, 0, 0 };
13532       GNode *rmdr, *rmvc;
13533
13534       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13535         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13536         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13537             ref.min_req_bitrate);
13538       }
13539
13540       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13541         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13542         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13543
13544 #ifndef GST_DISABLE_GST_DEBUG
13545         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13546 #endif
13547         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13548
13549         GST_LOG_OBJECT (qtdemux,
13550             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13551             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13552             bitmask, check_type);
13553         if (package == FOURCC_qtim && check_type == 0) {
13554           ref.min_req_qt_version = version;
13555         }
13556       }
13557
13558       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13559       if (rdrf) {
13560         guint32 ref_type;
13561         guint8 *ref_data;
13562         guint ref_len;
13563
13564         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13565         if (ref_len > 20) {
13566           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13567           ref_data = (guint8 *) rdrf->data + 20;
13568           if (ref_type == FOURCC_alis) {
13569             guint record_len, record_version, fn_len;
13570
13571             if (ref_len > 70) {
13572               /* MacOSX alias record, google for alias-layout.txt */
13573               record_len = QT_UINT16 (ref_data + 4);
13574               record_version = QT_UINT16 (ref_data + 4 + 2);
13575               fn_len = QT_UINT8 (ref_data + 50);
13576               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13577                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13578               }
13579             } else {
13580               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13581                   ref_len);
13582             }
13583           } else if (ref_type == FOURCC_url_) {
13584             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13585           } else {
13586             GST_DEBUG_OBJECT (qtdemux,
13587                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13588                 GST_FOURCC_ARGS (ref_type));
13589           }
13590           if (ref.location != NULL) {
13591             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13592             redirects =
13593                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13594           } else {
13595             GST_WARNING_OBJECT (qtdemux,
13596                 "Failed to extract redirect location from rdrf atom");
13597           }
13598         } else {
13599           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13600         }
13601       }
13602
13603       /* look for others */
13604       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13605     }
13606
13607     if (redirects != NULL) {
13608       qtdemux_process_redirects (qtdemux, redirects);
13609     }
13610   }
13611   return TRUE;
13612 }
13613
13614 static GstTagList *
13615 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13616 {
13617   const gchar *fmt;
13618
13619   if (tags == NULL) {
13620     tags = gst_tag_list_new_empty ();
13621     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13622   }
13623
13624   if (qtdemux->major_brand == FOURCC_mjp2)
13625     fmt = "Motion JPEG 2000";
13626   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13627     fmt = "3GP";
13628   else if (qtdemux->major_brand == FOURCC_qt__)
13629     fmt = "Quicktime";
13630   else if (qtdemux->fragmented)
13631     fmt = "ISO fMP4";
13632   else
13633     fmt = "ISO MP4/M4A";
13634
13635   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13636       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13637
13638   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13639       fmt, NULL);
13640
13641   return tags;
13642 }
13643
13644 /* we have read the complete moov node now.
13645  * This function parses all of the relevant info, creates the traks and
13646  * prepares all data structures for playback
13647  */
13648 static gboolean
13649 qtdemux_parse_tree (GstQTDemux * qtdemux)
13650 {
13651   GNode *mvhd;
13652   GNode *trak;
13653   GNode *udta;
13654   GNode *mvex;
13655   GstClockTime duration;
13656   GNode *pssh;
13657   guint64 creation_time;
13658   GstDateTime *datetime = NULL;
13659   gint version;
13660
13661   /* make sure we have a usable taglist */
13662   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13663
13664   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13665   if (mvhd == NULL) {
13666     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13667     return qtdemux_parse_redirects (qtdemux);
13668   }
13669
13670   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13671   if (version == 1) {
13672     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13673     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13674     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13675   } else if (version == 0) {
13676     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13677     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13678     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13679   } else {
13680     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13681     return FALSE;
13682   }
13683
13684   /* Moving qt creation time (secs since 1904) to unix time */
13685   if (creation_time != 0) {
13686     /* Try to use epoch first as it should be faster and more commonly found */
13687     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13688       GTimeVal now;
13689
13690       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13691       /* some data cleansing sanity */
13692       g_get_current_time (&now);
13693       if (now.tv_sec + 24 * 3600 < creation_time) {
13694         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13695       } else {
13696         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13697       }
13698     } else {
13699       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13700       GDateTime *dt, *dt_local;
13701
13702       dt = g_date_time_add_seconds (base_dt, creation_time);
13703       dt_local = g_date_time_to_local (dt);
13704       datetime = gst_date_time_new_from_g_date_time (dt_local);
13705
13706       g_date_time_unref (base_dt);
13707       g_date_time_unref (dt);
13708     }
13709   }
13710   if (datetime) {
13711     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13712     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13713         datetime, NULL);
13714     gst_date_time_unref (datetime);
13715   }
13716
13717   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13718   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13719
13720   /* check for fragmented file and get some (default) data */
13721   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13722   if (mvex) {
13723     GNode *mehd;
13724     GstByteReader mehd_data;
13725
13726     /* let track parsing or anyone know weird stuff might happen ... */
13727     qtdemux->fragmented = TRUE;
13728
13729     /* compensate for total duration */
13730     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13731     if (mehd)
13732       qtdemux_parse_mehd (qtdemux, &mehd_data);
13733   }
13734
13735   /* set duration in the segment info */
13736   gst_qtdemux_get_duration (qtdemux, &duration);
13737   if (duration) {
13738     qtdemux->segment.duration = duration;
13739     /* also do not exceed duration; stop is set that way post seek anyway,
13740      * and segment activation falls back to duration,
13741      * whereas loop only checks stop, so let's align this here as well */
13742     qtdemux->segment.stop = duration;
13743   }
13744
13745   /* parse all traks */
13746   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13747   while (trak) {
13748     qtdemux_parse_trak (qtdemux, trak);
13749     /* iterate all siblings */
13750     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13751   }
13752
13753   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13754
13755   /* find tags */
13756   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13757   if (udta) {
13758     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13759   } else {
13760     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13761   }
13762
13763   /* maybe also some tags in meta box */
13764   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13765   if (udta) {
13766     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13767     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13768   } else {
13769     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13770   }
13771
13772   /* parse any protection system info */
13773   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13774   while (pssh) {
13775     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13776     qtdemux_parse_pssh (qtdemux, pssh);
13777     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13778   }
13779
13780   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13781
13782   return TRUE;
13783 }
13784
13785 /* taken from ffmpeg */
13786 static int
13787 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13788 {
13789   int count = 4;
13790   int len = 0;
13791
13792   while (count--) {
13793     int c;
13794
13795     if (ptr >= end)
13796       return -1;
13797
13798     c = *ptr++;
13799     len = (len << 7) | (c & 0x7f);
13800     if (!(c & 0x80))
13801       break;
13802   }
13803   *end_out = ptr;
13804   return len;
13805 }
13806
13807 /* this can change the codec originally present in @list */
13808 static void
13809 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13810     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13811 {
13812   int len = QT_UINT32 (esds->data);
13813   guint8 *ptr = esds->data;
13814   guint8 *end = ptr + len;
13815   int tag;
13816   guint8 *data_ptr = NULL;
13817   int data_len = 0;
13818   guint8 object_type_id = 0;
13819   const char *codec_name = NULL;
13820   GstCaps *caps = NULL;
13821
13822   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13823   ptr += 8;
13824   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13825   ptr += 4;
13826   while (ptr + 1 < end) {
13827     tag = QT_UINT8 (ptr);
13828     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13829     ptr++;
13830     len = read_descr_size (ptr, end, &ptr);
13831     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13832
13833     /* Check the stated amount of data is available for reading */
13834     if (len < 0 || ptr + len > end)
13835       break;
13836
13837     switch (tag) {
13838       case ES_DESCRIPTOR_TAG:
13839         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13840         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13841         ptr += 3;
13842         break;
13843       case DECODER_CONFIG_DESC_TAG:{
13844         guint max_bitrate, avg_bitrate;
13845
13846         object_type_id = QT_UINT8 (ptr);
13847         max_bitrate = QT_UINT32 (ptr + 5);
13848         avg_bitrate = QT_UINT32 (ptr + 9);
13849         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13850         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13851         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13852         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13853         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13854         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13855           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13856               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13857         }
13858         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13859           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13860               avg_bitrate, NULL);
13861         }
13862         ptr += 13;
13863         break;
13864       }
13865       case DECODER_SPECIFIC_INFO_TAG:
13866         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13867         if (object_type_id == 0xe0 && len == 0x40) {
13868           guint8 *data;
13869           GstStructure *s;
13870           guint32 clut[16];
13871           gint i;
13872
13873           GST_DEBUG_OBJECT (qtdemux,
13874               "Have VOBSUB palette. Creating palette event");
13875           /* move to decConfigDescr data and read palette */
13876           data = ptr;
13877           for (i = 0; i < 16; i++) {
13878             clut[i] = QT_UINT32 (data);
13879             data += 4;
13880           }
13881
13882           s = gst_structure_new ("application/x-gst-dvd", "event",
13883               G_TYPE_STRING, "dvd-spu-clut-change",
13884               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13885               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13886               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13887               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13888               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13889               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13890               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13891               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13892               NULL);
13893
13894           /* store event and trigger custom processing */
13895           stream->pending_event =
13896               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13897         } else {
13898           /* Generic codec_data handler puts it on the caps */
13899           data_ptr = ptr;
13900           data_len = len;
13901         }
13902
13903         ptr += len;
13904         break;
13905       case SL_CONFIG_DESC_TAG:
13906         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13907         ptr += 1;
13908         break;
13909       default:
13910         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13911             tag);
13912         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13913         ptr += len;
13914         break;
13915     }
13916   }
13917
13918   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13919    * in use, and should also be used to override some other parameters for some
13920    * codecs. */
13921   switch (object_type_id) {
13922     case 0x20:                 /* MPEG-4 */
13923       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13924        * profile_and_level_indication */
13925       if (data_ptr != NULL && data_len >= 5 &&
13926           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13927         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13928             data_ptr + 4, data_len - 4);
13929       }
13930       break;                    /* Nothing special needed here */
13931     case 0x21:                 /* H.264 */
13932       codec_name = "H.264 / AVC";
13933       caps = gst_caps_new_simple ("video/x-h264",
13934           "stream-format", G_TYPE_STRING, "avc",
13935           "alignment", G_TYPE_STRING, "au", NULL);
13936       break;
13937     case 0x40:                 /* AAC (any) */
13938     case 0x66:                 /* AAC Main */
13939     case 0x67:                 /* AAC LC */
13940     case 0x68:                 /* AAC SSR */
13941       /* Override channels and rate based on the codec_data, as it's often
13942        * wrong. */
13943       /* Only do so for basic setup without HE-AAC extension */
13944       if (data_ptr && data_len == 2) {
13945         guint channels, rate;
13946
13947         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13948         if (channels > 0)
13949           entry->n_channels = channels;
13950
13951         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13952         if (rate > 0)
13953           entry->rate = rate;
13954       }
13955
13956       /* Set level and profile if possible */
13957       if (data_ptr != NULL && data_len >= 2) {
13958         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13959             data_ptr, data_len);
13960       } else {
13961         const gchar *profile_str = NULL;
13962         GstBuffer *buffer;
13963         GstMapInfo map;
13964         guint8 *codec_data;
13965         gint rate_idx, profile;
13966
13967         /* No codec_data, let's invent something.
13968          * FIXME: This is wrong for SBR! */
13969
13970         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13971
13972         buffer = gst_buffer_new_and_alloc (2);
13973         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13974         codec_data = map.data;
13975
13976         rate_idx =
13977             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13978             (stream)->rate);
13979
13980         switch (object_type_id) {
13981           case 0x66:
13982             profile_str = "main";
13983             profile = 0;
13984             break;
13985           case 0x67:
13986             profile_str = "lc";
13987             profile = 1;
13988             break;
13989           case 0x68:
13990             profile_str = "ssr";
13991             profile = 2;
13992             break;
13993           default:
13994             profile = 3;
13995             break;
13996         }
13997
13998         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13999         codec_data[1] =
14000             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14001
14002         gst_buffer_unmap (buffer, &map);
14003         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14004             GST_TYPE_BUFFER, buffer, NULL);
14005         gst_buffer_unref (buffer);
14006
14007         if (profile_str) {
14008           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14009               G_TYPE_STRING, profile_str, NULL);
14010         }
14011       }
14012       break;
14013     case 0x60:                 /* MPEG-2, various profiles */
14014     case 0x61:
14015     case 0x62:
14016     case 0x63:
14017     case 0x64:
14018     case 0x65:
14019       codec_name = "MPEG-2 video";
14020       caps = gst_caps_new_simple ("video/mpeg",
14021           "mpegversion", G_TYPE_INT, 2,
14022           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14023       break;
14024     case 0x69:                 /* MPEG-2 BC audio */
14025     case 0x6B:                 /* MPEG-1 audio */
14026       caps = gst_caps_new_simple ("audio/mpeg",
14027           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
14028       codec_name = "MPEG-1 audio";
14029       break;
14030     case 0x6A:                 /* MPEG-1 */
14031       codec_name = "MPEG-1 video";
14032       caps = gst_caps_new_simple ("video/mpeg",
14033           "mpegversion", G_TYPE_INT, 1,
14034           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14035       break;
14036     case 0x6C:                 /* MJPEG */
14037       caps =
14038           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14039           NULL);
14040       codec_name = "Motion-JPEG";
14041       break;
14042     case 0x6D:                 /* PNG */
14043       caps =
14044           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14045           NULL);
14046       codec_name = "PNG still images";
14047       break;
14048     case 0x6E:                 /* JPEG2000 */
14049       codec_name = "JPEG-2000";
14050       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14051       break;
14052     case 0xA4:                 /* Dirac */
14053       codec_name = "Dirac";
14054       caps = gst_caps_new_empty_simple ("video/x-dirac");
14055       break;
14056     case 0xA5:                 /* AC3 */
14057       codec_name = "AC-3 audio";
14058       caps = gst_caps_new_simple ("audio/x-ac3",
14059           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14060       break;
14061     case 0xA9:                 /* AC3 */
14062       codec_name = "DTS audio";
14063       caps = gst_caps_new_simple ("audio/x-dts",
14064           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14065       break;
14066     case 0xE1:                 /* QCELP */
14067       /* QCELP, the codec_data is a riff tag (little endian) with
14068        * 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). */
14069       caps = gst_caps_new_empty_simple ("audio/qcelp");
14070       codec_name = "QCELP";
14071       break;
14072     default:
14073       break;
14074   }
14075
14076   /* If we have a replacement caps, then change our caps for this stream */
14077   if (caps) {
14078     gst_caps_unref (entry->caps);
14079     entry->caps = caps;
14080   }
14081
14082   if (codec_name && list)
14083     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14084         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14085
14086   /* Add the codec_data attribute to caps, if we have it */
14087   if (data_ptr) {
14088     GstBuffer *buffer;
14089
14090     buffer = gst_buffer_new_and_alloc (data_len);
14091     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14092
14093     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14094     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14095
14096     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14097         buffer, NULL);
14098     gst_buffer_unref (buffer);
14099   }
14100
14101 }
14102
14103 static inline GstCaps *
14104 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14105 {
14106   GstCaps *caps;
14107   guint i;
14108   char *s, fourstr[5];
14109
14110   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14111   for (i = 0; i < 4; i++) {
14112     if (!g_ascii_isalnum (fourstr[i]))
14113       fourstr[i] = '_';
14114   }
14115   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14116   caps = gst_caps_new_empty_simple (s);
14117   g_free (s);
14118   return caps;
14119 }
14120
14121 #define _codec(name) \
14122   do { \
14123     if (codec_name) { \
14124       *codec_name = g_strdup (name); \
14125     } \
14126   } while (0)
14127
14128 static GstCaps *
14129 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14130     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14131     const guint8 * stsd_entry_data, gchar ** codec_name)
14132 {
14133   GstCaps *caps = NULL;
14134   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14135
14136   switch (fourcc) {
14137     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
14138       _codec ("PNG still images");
14139       caps = gst_caps_new_empty_simple ("image/png");
14140       break;
14141     case FOURCC_jpeg:
14142       _codec ("JPEG still images");
14143       caps =
14144           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14145           NULL);
14146       break;
14147     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14148     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14149     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14150     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14151       _codec ("Motion-JPEG");
14152       caps =
14153           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14154           NULL);
14155       break;
14156     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14157       _codec ("Motion-JPEG format B");
14158       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14159       break;
14160     case FOURCC_mjp2:
14161       _codec ("JPEG-2000");
14162       /* override to what it should be according to spec, avoid palette_data */
14163       entry->bits_per_sample = 24;
14164       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14165       break;
14166     case FOURCC_SVQ3:
14167       _codec ("Sorensen video v.3");
14168       caps = gst_caps_new_simple ("video/x-svq",
14169           "svqversion", G_TYPE_INT, 3, NULL);
14170       break;
14171     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14172     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14173       _codec ("Sorensen video v.1");
14174       caps = gst_caps_new_simple ("video/x-svq",
14175           "svqversion", G_TYPE_INT, 1, NULL);
14176       break;
14177     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14178       caps = gst_caps_new_empty_simple ("video/x-raw");
14179       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14180       _codec ("Windows Raw RGB");
14181       stream->alignment = 32;
14182       break;
14183     case FOURCC_raw_:
14184     {
14185       guint16 bps;
14186
14187       bps = QT_UINT16 (stsd_entry_data + 82);
14188       switch (bps) {
14189         case 15:
14190           format = GST_VIDEO_FORMAT_RGB15;
14191           break;
14192         case 16:
14193           format = GST_VIDEO_FORMAT_RGB16;
14194           break;
14195         case 24:
14196           format = GST_VIDEO_FORMAT_RGB;
14197           break;
14198         case 32:
14199           format = GST_VIDEO_FORMAT_ARGB;
14200           break;
14201         default:
14202           /* unknown */
14203           break;
14204       }
14205       break;
14206     }
14207     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14208       format = GST_VIDEO_FORMAT_I420;
14209       break;
14210     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14211     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14212       format = GST_VIDEO_FORMAT_I420;
14213       break;
14214     case FOURCC_2vuy:
14215     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14216       format = GST_VIDEO_FORMAT_UYVY;
14217       break;
14218     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14219       format = GST_VIDEO_FORMAT_v308;
14220       break;
14221     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14222       format = GST_VIDEO_FORMAT_v216;
14223       break;
14224     case FOURCC_v210:
14225       format = GST_VIDEO_FORMAT_v210;
14226       break;
14227     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14228       format = GST_VIDEO_FORMAT_r210;
14229       break;
14230       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14231          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14232          format = GST_VIDEO_FORMAT_v410;
14233          break;
14234        */
14235       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14236        * but different order than AYUV
14237        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14238        format = GST_VIDEO_FORMAT_v408;
14239        break;
14240        */
14241     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14242     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14243       _codec ("MPEG-1 video");
14244       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14245           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14246       break;
14247     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14248     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14249     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14250     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14251     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14252     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14253     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14254     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14255     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14256     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14257     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14258     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14259     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14260     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14261     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14262     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14263     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14264     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14265     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14266     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14267     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14268     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14269     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14270     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14271     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14272     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14273     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14274     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14275     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14276     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14277     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14278     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14279     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14280     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14281     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14282     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14283     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14284     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14285     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14286     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14287     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14288     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14289     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14290     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14291     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14292     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14293     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14294       _codec ("MPEG-2 video");
14295       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14296           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14297       break;
14298     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14299       _codec ("GIF still images");
14300       caps = gst_caps_new_empty_simple ("image/gif");
14301       break;
14302     case FOURCC_h263:
14303     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14304     case FOURCC_s263:
14305     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14306       _codec ("H.263");
14307       /* ffmpeg uses the height/width props, don't know why */
14308       caps = gst_caps_new_simple ("video/x-h263",
14309           "variant", G_TYPE_STRING, "itu", NULL);
14310       break;
14311     case FOURCC_mp4v:
14312     case FOURCC_MP4V:
14313       _codec ("MPEG-4 video");
14314       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14315           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14316       break;
14317     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14318     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14319       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14320       caps = gst_caps_new_simple ("video/x-msmpeg",
14321           "msmpegversion", G_TYPE_INT, 43, NULL);
14322       break;
14323     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14324       _codec ("DivX 3");
14325       caps = gst_caps_new_simple ("video/x-divx",
14326           "divxversion", G_TYPE_INT, 3, NULL);
14327       break;
14328     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14329     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14330       _codec ("DivX 4");
14331       caps = gst_caps_new_simple ("video/x-divx",
14332           "divxversion", G_TYPE_INT, 4, NULL);
14333       break;
14334     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14335       _codec ("DivX 5");
14336       caps = gst_caps_new_simple ("video/x-divx",
14337           "divxversion", G_TYPE_INT, 5, NULL);
14338       break;
14339
14340     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14341       _codec ("FFV1");
14342       caps = gst_caps_new_simple ("video/x-ffv",
14343           "ffvversion", G_TYPE_INT, 1, NULL);
14344       break;
14345
14346     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14347     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14348     case FOURCC_XVID:
14349     case FOURCC_xvid:
14350     case FOURCC_FMP4:
14351     case FOURCC_fmp4:
14352     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14353       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14354           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14355       _codec ("MPEG-4");
14356       break;
14357
14358     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14359       _codec ("Cinepak");
14360       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14361       break;
14362     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14363       _codec ("Apple QuickDraw");
14364       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14365       break;
14366     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14367       _codec ("Apple video");
14368       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14369       break;
14370     case FOURCC_H264:
14371     case FOURCC_avc1:
14372       _codec ("H.264 / AVC");
14373       caps = gst_caps_new_simple ("video/x-h264",
14374           "stream-format", G_TYPE_STRING, "avc",
14375           "alignment", G_TYPE_STRING, "au", NULL);
14376       break;
14377     case FOURCC_avc3:
14378       _codec ("H.264 / AVC");
14379       caps = gst_caps_new_simple ("video/x-h264",
14380           "stream-format", G_TYPE_STRING, "avc3",
14381           "alignment", G_TYPE_STRING, "au", NULL);
14382       break;
14383     case FOURCC_H265:
14384     case FOURCC_hvc1:
14385       _codec ("H.265 / HEVC");
14386       caps = gst_caps_new_simple ("video/x-h265",
14387           "stream-format", G_TYPE_STRING, "hvc1",
14388           "alignment", G_TYPE_STRING, "au", NULL);
14389       break;
14390     case FOURCC_hev1:
14391       _codec ("H.265 / HEVC");
14392       caps = gst_caps_new_simple ("video/x-h265",
14393           "stream-format", G_TYPE_STRING, "hev1",
14394           "alignment", G_TYPE_STRING, "au", NULL);
14395       break;
14396     case FOURCC_rle_:
14397       _codec ("Run-length encoding");
14398       caps = gst_caps_new_simple ("video/x-rle",
14399           "layout", G_TYPE_STRING, "quicktime", NULL);
14400       break;
14401     case FOURCC_WRLE:
14402       _codec ("Run-length encoding");
14403       caps = gst_caps_new_simple ("video/x-rle",
14404           "layout", G_TYPE_STRING, "microsoft", NULL);
14405       break;
14406     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14407     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14408       _codec ("Indeo Video 3");
14409       caps = gst_caps_new_simple ("video/x-indeo",
14410           "indeoversion", G_TYPE_INT, 3, NULL);
14411       break;
14412     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14413     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14414       _codec ("Intel Video 4");
14415       caps = gst_caps_new_simple ("video/x-indeo",
14416           "indeoversion", G_TYPE_INT, 4, NULL);
14417       break;
14418     case FOURCC_dvcp:
14419     case FOURCC_dvc_:
14420     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14421     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14422     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14423     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14424     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14425     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14426       _codec ("DV Video");
14427       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14428           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14429       break;
14430     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14431     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14432       _codec ("DVCPro50 Video");
14433       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14434           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14435       break;
14436     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14437     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14438       _codec ("DVCProHD Video");
14439       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14440           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14441       break;
14442     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14443       _codec ("Apple Graphics (SMC)");
14444       caps = gst_caps_new_empty_simple ("video/x-smc");
14445       break;
14446     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14447       _codec ("VP3");
14448       caps = gst_caps_new_empty_simple ("video/x-vp3");
14449       break;
14450     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14451       _codec ("VP6 Flash");
14452       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14453       break;
14454     case FOURCC_XiTh:
14455       _codec ("Theora");
14456       caps = gst_caps_new_empty_simple ("video/x-theora");
14457       /* theora uses one byte of padding in the data stream because it does not
14458        * allow 0 sized packets while theora does */
14459       entry->padding = 1;
14460       break;
14461     case FOURCC_drac:
14462       _codec ("Dirac");
14463       caps = gst_caps_new_empty_simple ("video/x-dirac");
14464       break;
14465     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14466       _codec ("TIFF still images");
14467       caps = gst_caps_new_empty_simple ("image/tiff");
14468       break;
14469     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14470       _codec ("Apple Intermediate Codec");
14471       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14472       break;
14473     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14474       _codec ("AVID DNxHD");
14475       caps = gst_caps_from_string ("video/x-dnxhd");
14476       break;
14477     case FOURCC_VP80:
14478       _codec ("On2 VP8");
14479       caps = gst_caps_from_string ("video/x-vp8");
14480       break;
14481     case FOURCC_apcs:
14482       _codec ("Apple ProRes LT");
14483       caps =
14484           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14485           NULL);
14486       break;
14487     case FOURCC_apch:
14488       _codec ("Apple ProRes HQ");
14489       caps =
14490           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14491           NULL);
14492       break;
14493     case FOURCC_apcn:
14494       _codec ("Apple ProRes");
14495       caps =
14496           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14497           "standard", NULL);
14498       break;
14499     case FOURCC_apco:
14500       _codec ("Apple ProRes Proxy");
14501       caps =
14502           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14503           "proxy", NULL);
14504       break;
14505     case FOURCC_ap4h:
14506       _codec ("Apple ProRes 4444");
14507       caps =
14508           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14509           "4444", NULL);
14510       break;
14511     case FOURCC_ap4x:
14512       _codec ("Apple ProRes 4444 XQ");
14513       caps =
14514           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14515           "4444xq", NULL);
14516       break;
14517     case FOURCC_cfhd:
14518       _codec ("GoPro CineForm");
14519       caps = gst_caps_from_string ("video/x-cineform");
14520       break;
14521     case FOURCC_vc_1:
14522     case FOURCC_ovc1:
14523       _codec ("VC-1");
14524       caps = gst_caps_new_simple ("video/x-wmv",
14525           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14526       break;
14527     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14528     default:
14529     {
14530       caps = _get_unknown_codec_name ("video", fourcc);
14531       break;
14532     }
14533   }
14534
14535   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14536     GstVideoInfo info;
14537
14538     gst_video_info_init (&info);
14539     gst_video_info_set_format (&info, format, entry->width, entry->height);
14540
14541     caps = gst_video_info_to_caps (&info);
14542     *codec_name = gst_pb_utils_get_codec_description (caps);
14543
14544     /* enable clipping for raw video streams */
14545     stream->need_clip = TRUE;
14546     stream->alignment = 32;
14547   }
14548
14549   return caps;
14550 }
14551
14552 static guint
14553 round_up_pow2 (guint n)
14554 {
14555   n = n - 1;
14556   n = n | (n >> 1);
14557   n = n | (n >> 2);
14558   n = n | (n >> 4);
14559   n = n | (n >> 8);
14560   n = n | (n >> 16);
14561   return n + 1;
14562 }
14563
14564 static GstCaps *
14565 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14566     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14567     int len, gchar ** codec_name)
14568 {
14569   GstCaps *caps;
14570   const GstStructure *s;
14571   const gchar *name;
14572   gint endian = 0;
14573   GstAudioFormat format = 0;
14574   gint depth;
14575
14576   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14577
14578   depth = entry->bytes_per_packet * 8;
14579
14580   switch (fourcc) {
14581     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14582     case FOURCC_raw_:
14583       /* 8-bit audio is unsigned */
14584       if (depth == 8)
14585         format = GST_AUDIO_FORMAT_U8;
14586       /* otherwise it's signed and big-endian just like 'twos' */
14587     case FOURCC_twos:
14588       endian = G_BIG_ENDIAN;
14589       /* fall-through */
14590     case FOURCC_sowt:
14591     {
14592       gchar *str;
14593
14594       if (!endian)
14595         endian = G_LITTLE_ENDIAN;
14596
14597       if (!format)
14598         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14599
14600       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14601       _codec (str);
14602       g_free (str);
14603
14604       caps = gst_caps_new_simple ("audio/x-raw",
14605           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14606           "layout", G_TYPE_STRING, "interleaved", NULL);
14607       stream->alignment = GST_ROUND_UP_8 (depth);
14608       stream->alignment = round_up_pow2 (stream->alignment);
14609       break;
14610     }
14611     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14612       _codec ("Raw 64-bit floating-point audio");
14613       caps = gst_caps_new_simple ("audio/x-raw",
14614           "format", G_TYPE_STRING, "F64BE",
14615           "layout", G_TYPE_STRING, "interleaved", NULL);
14616       stream->alignment = 8;
14617       break;
14618     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14619       _codec ("Raw 32-bit floating-point audio");
14620       caps = gst_caps_new_simple ("audio/x-raw",
14621           "format", G_TYPE_STRING, "F32BE",
14622           "layout", G_TYPE_STRING, "interleaved", NULL);
14623       stream->alignment = 4;
14624       break;
14625     case FOURCC_in24:
14626       _codec ("Raw 24-bit PCM audio");
14627       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14628        * endian later */
14629       caps = gst_caps_new_simple ("audio/x-raw",
14630           "format", G_TYPE_STRING, "S24BE",
14631           "layout", G_TYPE_STRING, "interleaved", NULL);
14632       stream->alignment = 4;
14633       break;
14634     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14635       _codec ("Raw 32-bit PCM audio");
14636       caps = gst_caps_new_simple ("audio/x-raw",
14637           "format", G_TYPE_STRING, "S32BE",
14638           "layout", G_TYPE_STRING, "interleaved", NULL);
14639       stream->alignment = 4;
14640       break;
14641     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14642       _codec ("Raw 16-bit PCM audio");
14643       caps = gst_caps_new_simple ("audio/x-raw",
14644           "format", G_TYPE_STRING, "S16LE",
14645           "layout", G_TYPE_STRING, "interleaved", NULL);
14646       stream->alignment = 2;
14647       break;
14648     case FOURCC_ulaw:
14649       _codec ("Mu-law audio");
14650       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14651       break;
14652     case FOURCC_alaw:
14653       _codec ("A-law audio");
14654       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14655       break;
14656     case 0x0200736d:
14657     case 0x6d730002:
14658       _codec ("Microsoft ADPCM");
14659       /* Microsoft ADPCM-ACM code 2 */
14660       caps = gst_caps_new_simple ("audio/x-adpcm",
14661           "layout", G_TYPE_STRING, "microsoft", NULL);
14662       break;
14663     case 0x1100736d:
14664     case 0x6d730011:
14665       _codec ("DVI/IMA ADPCM");
14666       caps = gst_caps_new_simple ("audio/x-adpcm",
14667           "layout", G_TYPE_STRING, "dvi", NULL);
14668       break;
14669     case 0x1700736d:
14670     case 0x6d730017:
14671       _codec ("DVI/Intel IMA ADPCM");
14672       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14673       caps = gst_caps_new_simple ("audio/x-adpcm",
14674           "layout", G_TYPE_STRING, "quicktime", NULL);
14675       break;
14676     case 0x5500736d:
14677     case 0x6d730055:
14678       /* MPEG layer 3, CBR only (pre QT4.1) */
14679     case FOURCC__mp3:
14680       _codec ("MPEG-1 layer 3");
14681       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14682       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14683           "mpegversion", G_TYPE_INT, 1, NULL);
14684       break;
14685     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14686       _codec ("MPEG-1 layer 2");
14687       /* MPEG layer 2 */
14688       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14689           "mpegversion", G_TYPE_INT, 1, NULL);
14690       break;
14691     case 0x20736d:
14692     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14693       _codec ("EAC-3 audio");
14694       caps = gst_caps_new_simple ("audio/x-eac3",
14695           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14696       entry->sampled = TRUE;
14697       break;
14698     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14699     case FOURCC_ac_3:
14700       _codec ("AC-3 audio");
14701       caps = gst_caps_new_simple ("audio/x-ac3",
14702           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14703       entry->sampled = TRUE;
14704       break;
14705     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14706     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14707       _codec ("DTS audio");
14708       caps = gst_caps_new_simple ("audio/x-dts",
14709           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14710       entry->sampled = TRUE;
14711       break;
14712     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14713     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14714       _codec ("DTS-HD audio");
14715       caps = gst_caps_new_simple ("audio/x-dts",
14716           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14717       entry->sampled = TRUE;
14718       break;
14719     case FOURCC_MAC3:
14720       _codec ("MACE-3");
14721       caps = gst_caps_new_simple ("audio/x-mace",
14722           "maceversion", G_TYPE_INT, 3, NULL);
14723       break;
14724     case FOURCC_MAC6:
14725       _codec ("MACE-6");
14726       caps = gst_caps_new_simple ("audio/x-mace",
14727           "maceversion", G_TYPE_INT, 6, NULL);
14728       break;
14729     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14730       /* ogg/vorbis */
14731       caps = gst_caps_new_empty_simple ("application/ogg");
14732       break;
14733     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14734       _codec ("DV audio");
14735       caps = gst_caps_new_empty_simple ("audio/x-dv");
14736       break;
14737     case FOURCC_mp4a:
14738       _codec ("MPEG-4 AAC audio");
14739       caps = gst_caps_new_simple ("audio/mpeg",
14740           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14741           "stream-format", G_TYPE_STRING, "raw", NULL);
14742       break;
14743     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14744       _codec ("QDesign Music");
14745       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14746       break;
14747     case FOURCC_QDM2:
14748       _codec ("QDesign Music v.2");
14749       /* FIXME: QDesign music version 2 (no constant) */
14750       if (FALSE && data) {
14751         caps = gst_caps_new_simple ("audio/x-qdm2",
14752             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14753             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14754             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14755       } else {
14756         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14757       }
14758       break;
14759     case FOURCC_agsm:
14760       _codec ("GSM audio");
14761       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14762       break;
14763     case FOURCC_samr:
14764       _codec ("AMR audio");
14765       caps = gst_caps_new_empty_simple ("audio/AMR");
14766       break;
14767     case FOURCC_sawb:
14768       _codec ("AMR-WB audio");
14769       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14770       break;
14771     case FOURCC_ima4:
14772       _codec ("Quicktime IMA ADPCM");
14773       caps = gst_caps_new_simple ("audio/x-adpcm",
14774           "layout", G_TYPE_STRING, "quicktime", NULL);
14775       break;
14776     case FOURCC_alac:
14777       _codec ("Apple lossless audio");
14778       caps = gst_caps_new_empty_simple ("audio/x-alac");
14779       break;
14780     case FOURCC_fLaC:
14781       _codec ("Free Lossless Audio Codec");
14782       caps = gst_caps_new_simple ("audio/x-flac",
14783           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14784       break;
14785     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14786       _codec ("QualComm PureVoice");
14787       caps = gst_caps_from_string ("audio/qcelp");
14788       break;
14789     case FOURCC_wma_:
14790     case FOURCC_owma:
14791       _codec ("WMA");
14792       caps = gst_caps_new_empty_simple ("audio/x-wma");
14793       break;
14794     case FOURCC_opus:
14795       _codec ("Opus");
14796       caps = gst_caps_new_empty_simple ("audio/x-opus");
14797       break;
14798     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14799     {
14800       guint32 flags = 0;
14801       guint32 depth = 0;
14802       guint32 width = 0;
14803       GstAudioFormat format;
14804       enum
14805       {
14806         FLAG_IS_FLOAT = 0x1,
14807         FLAG_IS_BIG_ENDIAN = 0x2,
14808         FLAG_IS_SIGNED = 0x4,
14809         FLAG_IS_PACKED = 0x8,
14810         FLAG_IS_ALIGNED_HIGH = 0x10,
14811         FLAG_IS_NON_INTERLEAVED = 0x20
14812       };
14813       _codec ("Raw LPCM audio");
14814
14815       if (data && len >= 56) {
14816         depth = QT_UINT32 (data + 40);
14817         flags = QT_UINT32 (data + 44);
14818         width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
14819       }
14820       if ((flags & FLAG_IS_FLOAT) == 0) {
14821         if (depth == 0)
14822           depth = 16;
14823         if (width == 0)
14824           width = 16;
14825         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14826             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14827             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14828         caps = gst_caps_new_simple ("audio/x-raw",
14829             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14830             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14831             "non-interleaved" : "interleaved", NULL);
14832         stream->alignment = GST_ROUND_UP_8 (depth);
14833         stream->alignment = round_up_pow2 (stream->alignment);
14834       } else {
14835         if (width == 0)
14836           width = 32;
14837         if (width == 64) {
14838           if (flags & FLAG_IS_BIG_ENDIAN)
14839             format = GST_AUDIO_FORMAT_F64BE;
14840           else
14841             format = GST_AUDIO_FORMAT_F64LE;
14842         } else {
14843           if (flags & FLAG_IS_BIG_ENDIAN)
14844             format = GST_AUDIO_FORMAT_F32BE;
14845           else
14846             format = GST_AUDIO_FORMAT_F32LE;
14847         }
14848         caps = gst_caps_new_simple ("audio/x-raw",
14849             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14850             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14851             "non-interleaved" : "interleaved", NULL);
14852         stream->alignment = width / 8;
14853       }
14854       break;
14855     }
14856     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14857       /* ? */
14858     default:
14859     {
14860       caps = _get_unknown_codec_name ("audio", fourcc);
14861       break;
14862     }
14863   }
14864
14865   if (caps) {
14866     GstCaps *templ_caps =
14867         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14868     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14869     gst_caps_unref (caps);
14870     gst_caps_unref (templ_caps);
14871     caps = intersection;
14872   }
14873
14874   /* enable clipping for raw audio streams */
14875   s = gst_caps_get_structure (caps, 0);
14876   name = gst_structure_get_name (s);
14877   if (g_str_has_prefix (name, "audio/x-raw")) {
14878     stream->need_clip = TRUE;
14879     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14880     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14881   }
14882   return caps;
14883 }
14884
14885 static GstCaps *
14886 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14887     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14888     const guint8 * stsd_entry_data, gchar ** codec_name)
14889 {
14890   GstCaps *caps;
14891
14892   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14893
14894   switch (fourcc) {
14895     case FOURCC_mp4s:
14896       _codec ("DVD subtitle");
14897       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14898       stream->need_process = TRUE;
14899       break;
14900     case FOURCC_text:
14901       _codec ("Quicktime timed text");
14902       goto text;
14903     case FOURCC_tx3g:
14904       _codec ("3GPP timed text");
14905     text:
14906       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14907           "utf8", NULL);
14908       /* actual text piece needs to be extracted */
14909       stream->need_process = TRUE;
14910       break;
14911     case FOURCC_stpp:
14912       _codec ("XML subtitles");
14913       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14914       break;
14915     default:
14916     {
14917       caps = _get_unknown_codec_name ("text", fourcc);
14918       break;
14919     }
14920   }
14921   return caps;
14922 }
14923
14924 static GstCaps *
14925 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14926     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14927     const guint8 * stsd_entry_data, gchar ** codec_name)
14928 {
14929   GstCaps *caps;
14930
14931   switch (fourcc) {
14932     case FOURCC_m1v:
14933       _codec ("MPEG 1 video");
14934       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14935           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14936       break;
14937     default:
14938       caps = NULL;
14939       break;
14940   }
14941   return caps;
14942 }
14943
14944 static void
14945 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14946     const gchar * system_id)
14947 {
14948   gint i;
14949
14950   if (!qtdemux->protection_system_ids)
14951     qtdemux->protection_system_ids =
14952         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14953   /* Check whether we already have an entry for this system ID. */
14954   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14955     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14956     if (g_ascii_strcasecmp (system_id, id) == 0) {
14957       return;
14958     }
14959   }
14960   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14961   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14962           -1));
14963 }