qtdemux: fix memory leak
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 /**
30  * SECTION:element-qtdemux
31  *
32  * Demuxes a .mov file into raw or compressed audio and/or video streams.
33  *
34  * This element supports both push and pull-based scheduling, depending on the
35  * capabilities of the upstream elements.
36  *
37  * <refsect2>
38  * <title>Example launch line</title>
39  * |[
40  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
41  * ]| Play (parse and decode) a .mov file and try to output it to
42  * an automatically detected soundcard and videosink. If the MOV file contains
43  * compressed audio or video data, this will only work if you have the
44  * right decoder elements/plugins installed.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #include "gst/gst-i18n-plugin.h"
53
54 #include <glib/gprintf.h>
55 #include <gst/tag/tag.h>
56 #include <gst/audio/audio.h>
57 #include <gst/video/video.h>
58
59 #include "qtatomparser.h"
60 #include "qtdemux_types.h"
61 #include "qtdemux_dump.h"
62 #include "fourcc.h"
63 #include "descriptors.h"
64 #include "qtdemux_lang.h"
65 #include "qtdemux.h"
66 #include "qtpalette.h"
67
68 #include "gst/riff/riff-media.h"
69 #include "gst/riff/riff-read.h"
70
71 #include <gst/pbutils/pbutils.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include <math.h>
78 #include <gst/math-compat.h>
79
80 #ifdef HAVE_ZLIB
81 # include <zlib.h>
82 #endif
83
84 /* max. size considered 'sane' for non-mdat atoms */
85 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
86
87 /* if the sample index is larger than this, something is likely wrong */
88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
89
90 /* For converting qt creation times to unix epoch times */
91 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
92 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
93 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
94     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
95
96 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
97
98 GST_DEBUG_CATEGORY (qtdemux_debug);
99
100 /*typedef struct _QtNode QtNode; */
101 typedef struct _QtDemuxSegment QtDemuxSegment;
102 typedef struct _QtDemuxSample QtDemuxSample;
103
104 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
105
106 /*struct _QtNode
107 {
108   guint32 type;
109   guint8 *data;
110   gint len;
111 };*/
112
113 struct _QtDemuxSample
114 {
115   guint32 size;
116   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
117   guint64 offset;
118   guint64 timestamp;            /* DTS In mov time */
119   guint32 duration;             /* In mov time */
120   gboolean keyframe;            /* TRUE when this packet is a keyframe */
121 };
122
123 /* Macros for converting to/from timescale */
124 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
125 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
126
127 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
128 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
129
130 /* timestamp is the DTS */
131 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
132 /* timestamp + offset is the PTS */
133 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
134 /* timestamp + duration - dts is the duration */
135 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
136
137 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
138
139 /*
140  * Quicktime has tracks and segments. A track is a continuous piece of
141  * multimedia content. The track is not always played from start to finish but
142  * instead, pieces of the track are 'cut out' and played in sequence. This is
143  * what the segments do.
144  *
145  * Inside the track we have keyframes (K) and delta frames. The track has its
146  * own timing, which starts from 0 and extends to end. The position in the track
147  * is called the media_time.
148  *
149  * The segments now describe the pieces that should be played from this track
150  * and are basically tuples of media_time/duration/rate entries. We can have
151  * multiple segments and they are all played after one another. An example:
152  *
153  * segment 1: media_time: 1 second, duration: 1 second, rate 1
154  * segment 2: media_time: 3 second, duration: 2 second, rate 2
155  *
156  * To correctly play back this track, one must play: 1 second of media starting
157  * from media_time 1 followed by 2 seconds of media starting from media_time 3
158  * at a rate of 2.
159  *
160  * Each of the segments will be played at a specific time, the first segment at
161  * time 0, the second one after the duration of the first one, etc.. Note that
162  * the time in resulting playback is not identical to the media_time of the
163  * track anymore.
164  *
165  * Visually, assuming the track has 4 second of media_time:
166  *
167  *                (a)                   (b)          (c)              (d)
168  *         .-----------------------------------------------------------.
169  * track:  | K.....K.........K........K.......K.......K...........K... |
170  *         '-----------------------------------------------------------'
171  *         0              1              2              3              4
172  *           .------------^              ^   .----------^              ^
173  *          /              .-------------'  /       .------------------'
174  *         /              /          .-----'       /
175  *         .--------------.         .--------------.
176  *         | segment 1    |         | segment 2    |
177  *         '--------------'         '--------------'
178  *
179  * The challenge here is to cut out the right pieces of the track for each of
180  * the playback segments. This fortunately can easily be done with the SEGMENT
181  * events of GStreamer.
182  *
183  * For playback of segment 1, we need to provide the decoder with the keyframe
184  * (a), in the above figure, but we must instruct it only to output the decoded
185  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
186  * position set to the time of the segment: 0.
187  *
188  * We then proceed to push data from keyframe (a) to frame (b). The decoder
189  * decodes but clips all before media_time 1.
190  *
191  * After finishing a segment, we push out a new SEGMENT event with the clipping
192  * boundaries of the new data.
193  *
194  * This is a good usecase for the GStreamer accumulated SEGMENT events.
195  */
196
197 struct _QtDemuxSegment
198 {
199   /* global time and duration, all gst time */
200   GstClockTime time;
201   GstClockTime stop_time;
202   GstClockTime duration;
203   /* media time of trak, all gst time */
204   GstClockTime media_start;
205   GstClockTime media_stop;
206   gdouble rate;
207   /* Media start time in trak timescale units */
208   guint32 trak_media_start;
209 };
210
211 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
212
213 /* Used with fragmented MP4 files (mfra atom) */
214 typedef struct
215 {
216   GstClockTime ts;
217   guint64 moof_offset;
218 } QtDemuxRandomAccessEntry;
219
220 struct _QtDemuxStream
221 {
222   GstPad *pad;
223
224   /* stream type */
225   guint32 subtype;
226   GstCaps *caps;
227   guint32 fourcc;
228   gboolean sparse;
229
230   gboolean new_caps;
231   gboolean new_stream;          /* signals that a stream_start is required */
232   gboolean on_keyframe;         /* if this stream last pushed buffer was a
233                                  * keyframe. This is important to identify
234                                  * where to stop pushing buffers after a
235                                  * segment stop time */
236
237   /* if the stream has a redirect URI in its headers, we store it here */
238   gchar *redirect_uri;
239
240   /* track id */
241   guint track_id;
242
243   /* duration/scale */
244   guint64 duration;             /* in timescale */
245   guint32 timescale;
246
247   /* language */
248   gchar lang_id[4];             /* ISO 639-2T language code */
249
250   /* our samples */
251   guint32 n_samples;
252   QtDemuxSample *samples;
253   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
254   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
255                                    the framerate, in timescale units */
256   guint32 offset_in_sample;
257   guint32 max_buffer_size;
258
259   /* if we use chunks or samples */
260   gboolean sampled;
261   guint padding;
262
263   /* video info */
264   gint width;
265   gint height;
266   /* aspect ratio */
267   gint display_width;
268   gint display_height;
269   gint par_w;
270   gint par_h;
271   /* Numerator/denominator framerate */
272   gint fps_n;
273   gint fps_d;
274   guint16 bits_per_sample;
275   guint16 color_table_id;
276   GstMemory *rgb8_palette;
277
278   /* audio info */
279   gdouble rate;
280   gint n_channels;
281   guint samples_per_packet;
282   guint samples_per_frame;
283   guint bytes_per_packet;
284   guint bytes_per_sample;
285   guint bytes_per_frame;
286   guint compression;
287
288   /* allocation */
289   gboolean use_allocator;
290   GstAllocator *allocator;
291   GstAllocationParams params;
292
293   /* when a discontinuity is pending */
294   gboolean discont;
295
296   /* list of buffers to push first */
297   GSList *buffers;
298
299   /* if we need to clip this buffer. This is only needed for uncompressed
300    * data */
301   gboolean need_clip;
302
303   /* buffer needs some custom processing, e.g. subtitles */
304   gboolean need_process;
305
306   /* current position */
307   guint32 segment_index;
308   guint32 sample_index;
309   GstClockTime time_position;   /* in gst time */
310   guint64 accumulated_base;
311
312   /* the Gst segment we are processing out, used for clipping */
313   GstSegment segment;
314   guint32 segment_seqnum;       /* segment event seqnum obtained from seek */
315
316   /* quicktime segments */
317   guint32 n_segments;
318   QtDemuxSegment *segments;
319   gboolean dummy_segment;
320   guint32 from_sample;
321   guint32 to_sample;
322
323   gboolean sent_eos;
324   GstTagList *pending_tags;
325   gboolean send_global_tags;
326
327   GstEvent *pending_event;
328
329   GstByteReader stco;
330   GstByteReader stsz;
331   GstByteReader stsc;
332   GstByteReader stts;
333   GstByteReader stss;
334   GstByteReader stps;
335   GstByteReader ctts;
336
337   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
338   gint64 stbl_index;
339   /* stco */
340   guint co_size;
341   GstByteReader co_chunk;
342   guint32 first_chunk;
343   guint32 current_chunk;
344   guint32 last_chunk;
345   guint32 samples_per_chunk;
346   guint32 stco_sample_index;
347   /* stsz */
348   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
349   /* stsc */
350   guint32 stsc_index;
351   guint32 n_samples_per_chunk;
352   guint32 stsc_chunk_index;
353   guint32 stsc_sample_index;
354   guint64 chunk_offset;
355   /* stts */
356   guint32 stts_index;
357   guint32 stts_samples;
358   guint32 n_sample_times;
359   guint32 stts_sample_index;
360   guint64 stts_time;
361   guint32 stts_duration;
362   /* stss */
363   gboolean stss_present;
364   guint32 n_sample_syncs;
365   guint32 stss_index;
366   /* stps */
367   gboolean stps_present;
368   guint32 n_sample_partial_syncs;
369   guint32 stps_index;
370   QtDemuxRandomAccessEntry *ra_entries;
371   guint n_ra_entries;
372
373   const QtDemuxRandomAccessEntry *pending_seek;
374
375   /* ctts */
376   gboolean ctts_present;
377   guint32 n_composition_times;
378   guint32 ctts_index;
379   guint32 ctts_sample_index;
380   guint32 ctts_count;
381   gint32 ctts_soffset;
382
383   /* cslg */
384   guint32 cslg_shift;
385
386   /* fragmented */
387   gboolean parsed_trex;
388   guint32 def_sample_duration;
389   guint32 def_sample_size;
390   guint32 def_sample_flags;
391
392   gboolean disabled;
393
394   /* stereoscopic video streams */
395   GstVideoMultiviewMode multiview_mode;
396   GstVideoMultiviewFlags multiview_flags;
397
398   /* protected streams */
399   gboolean protected;
400   guint32 protection_scheme_type;
401   guint32 protection_scheme_version;
402   gpointer protection_scheme_info;      /* specific to the protection scheme */
403   GQueue protection_scheme_event_queue;
404 };
405
406 /* Contains properties and cryptographic info for a set of samples from a
407  * track protected using Common Encryption (cenc) */
408 struct _QtDemuxCencSampleSetInfo
409 {
410   GstStructure *default_properties;
411
412   /* @crypto_info holds one GstStructure per sample */
413   GPtrArray *crypto_info;
414 };
415
416 enum QtDemuxState
417 {
418   QTDEMUX_STATE_INITIAL,        /* Initial state (haven't got the header yet) */
419   QTDEMUX_STATE_HEADER,         /* Parsing the header */
420   QTDEMUX_STATE_MOVIE,          /* Parsing/Playing the media data */
421   QTDEMUX_STATE_BUFFER_MDAT     /* Buffering the mdat atom */
422 };
423
424 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
425 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
426     guint32 fourcc, GstByteReader * parser);
427 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
428 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
429     guint32 fourcc, GstByteReader * parser);
430
431 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
432
433 static GstStaticPadTemplate gst_qtdemux_sink_template =
434     GST_STATIC_PAD_TEMPLATE ("sink",
435     GST_PAD_SINK,
436     GST_PAD_ALWAYS,
437     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
438         "application/x-3gp")
439     );
440
441 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
442 GST_STATIC_PAD_TEMPLATE ("video_%u",
443     GST_PAD_SRC,
444     GST_PAD_SOMETIMES,
445     GST_STATIC_CAPS_ANY);
446
447 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
448 GST_STATIC_PAD_TEMPLATE ("audio_%u",
449     GST_PAD_SRC,
450     GST_PAD_SOMETIMES,
451     GST_STATIC_CAPS_ANY);
452
453 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
454 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
455     GST_PAD_SRC,
456     GST_PAD_SOMETIMES,
457     GST_STATIC_CAPS_ANY);
458
459 #define gst_qtdemux_parent_class parent_class
460 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
461
462 static void gst_qtdemux_dispose (GObject * object);
463
464 static guint32
465 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
466     GstClockTime media_time);
467 static guint32
468 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
469     QtDemuxStream * str, gint64 media_offset);
470
471 #if 0
472 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
473 static GstIndex *gst_qtdemux_get_index (GstElement * element);
474 #endif
475 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
476     GstStateChange transition);
477 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
478 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
479     GstObject * parent, GstPadMode mode, gboolean active);
480
481 static void gst_qtdemux_loop (GstPad * pad);
482 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
483     GstBuffer * inbuf);
484 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
485     GstEvent * event);
486 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
487 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
488     QtDemuxStream * stream);
489 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
490     gboolean force);
491
492 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
493     const guint8 * buffer, guint length);
494 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
495     const guint8 * buffer, guint length);
496 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
497 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
498     GNode * udta);
499
500 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
501     QtDemuxStream * stream, GNode * esds, GstTagList * list);
502 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
503     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
504     gchar ** codec_name);
505 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
506     QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len,
507     gchar ** codec_name);
508 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
509     QtDemuxStream * stream, guint32 fourcc, const guint8 * data,
510     gchar ** codec_name);
511 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
512     QtDemuxStream * stream, guint32 fourcc, const guint8 * stsd_data,
513     gchar ** codec_name);
514
515 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
516     QtDemuxStream * stream, guint32 n);
517 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
518 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
519     QtDemuxStream * stream);
520 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
521     QtDemuxStream * stream);
522 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
523 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
524 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
525     QtDemuxStream * stream);
526
527 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
528 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
529
530 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
531     const gchar * id);
532
533 static void
534 gst_qtdemux_class_init (GstQTDemuxClass * klass)
535 {
536   GObjectClass *gobject_class;
537   GstElementClass *gstelement_class;
538
539   gobject_class = (GObjectClass *) klass;
540   gstelement_class = (GstElementClass *) klass;
541
542   parent_class = g_type_class_peek_parent (klass);
543
544   gobject_class->dispose = gst_qtdemux_dispose;
545
546   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
547 #if 0
548   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
549   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
550 #endif
551
552   gst_tag_register_musicbrainz_tags ();
553
554   gst_element_class_add_pad_template (gstelement_class,
555       gst_static_pad_template_get (&gst_qtdemux_sink_template));
556   gst_element_class_add_pad_template (gstelement_class,
557       gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
558   gst_element_class_add_pad_template (gstelement_class,
559       gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
560   gst_element_class_add_pad_template (gstelement_class,
561       gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
562   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
563       "Codec/Demuxer",
564       "Demultiplex a QuickTime file into audio and video streams",
565       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
566
567   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
568
569 }
570
571 static void
572 gst_qtdemux_init (GstQTDemux * qtdemux)
573 {
574   qtdemux->sinkpad =
575       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
576   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
577   gst_pad_set_activatemode_function (qtdemux->sinkpad,
578       qtdemux_sink_activate_mode);
579   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
580   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
581   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
582
583   qtdemux->state = QTDEMUX_STATE_INITIAL;
584   qtdemux->pullbased = FALSE;
585   qtdemux->posted_redirect = FALSE;
586   qtdemux->neededbytes = 16;
587   qtdemux->todrop = 0;
588   qtdemux->adapter = gst_adapter_new ();
589   qtdemux->offset = 0;
590   qtdemux->first_mdat = -1;
591   qtdemux->got_moov = FALSE;
592   qtdemux->mdatoffset = -1;
593   qtdemux->mdatbuffer = NULL;
594   qtdemux->restoredata_buffer = NULL;
595   qtdemux->restoredata_offset = -1;
596   qtdemux->fragment_start = -1;
597   qtdemux->fragment_start_offset = -1;
598   qtdemux->media_caps = NULL;
599   qtdemux->exposed = FALSE;
600   qtdemux->mss_mode = FALSE;
601   qtdemux->pending_newsegment = NULL;
602   qtdemux->upstream_format_is_time = FALSE;
603   qtdemux->have_group_id = FALSE;
604   qtdemux->group_id = G_MAXUINT;
605   qtdemux->protection_system_ids = NULL;
606   g_queue_init (&qtdemux->protection_event_queue);
607   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
608   qtdemux->flowcombiner = gst_flow_combiner_new ();
609
610   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
611 }
612
613 static void
614 gst_qtdemux_dispose (GObject * object)
615 {
616   GstQTDemux *qtdemux = GST_QTDEMUX (object);
617
618   if (qtdemux->adapter) {
619     g_object_unref (G_OBJECT (qtdemux->adapter));
620     qtdemux->adapter = NULL;
621   }
622   gst_flow_combiner_free (qtdemux->flowcombiner);
623   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
624       NULL);
625   g_queue_clear (&qtdemux->protection_event_queue);
626
627   G_OBJECT_CLASS (parent_class)->dispose (object);
628 }
629
630 static void
631 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
632 {
633   if (qtdemux->posted_redirect) {
634     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
635         (_("This file contains no playable streams.")),
636         ("no known streams found, a redirect message has been posted"));
637   } else {
638     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
639         (_("This file contains no playable streams.")),
640         ("no known streams found"));
641   }
642 }
643
644 static GstBuffer *
645 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
646 {
647   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
648       mem, size, 0, size, mem, free_func);
649 }
650
651 static GstFlowReturn
652 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
653     GstBuffer ** buf)
654 {
655   GstFlowReturn flow;
656   GstMapInfo map;
657   gsize bsize;
658
659   if (G_UNLIKELY (size == 0)) {
660     GstFlowReturn ret;
661     GstBuffer *tmp = NULL;
662
663     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
664     if (ret != GST_FLOW_OK)
665       return ret;
666
667     gst_buffer_map (tmp, &map, GST_MAP_READ);
668     size = QT_UINT32 (map.data);
669     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
670
671     gst_buffer_unmap (tmp, &map);
672     gst_buffer_unref (tmp);
673   }
674
675   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
676   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
677     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
678       /* we're pulling header but already got most interesting bits,
679        * so never mind the rest (e.g. tags) (that much) */
680       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
681           size);
682       return GST_FLOW_EOS;
683     } else {
684       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
685           (_("This file is invalid and cannot be played.")),
686           ("atom has bogus size %" G_GUINT64_FORMAT, size));
687       return GST_FLOW_ERROR;
688     }
689   }
690
691   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
692
693   if (G_UNLIKELY (flow != GST_FLOW_OK))
694     return flow;
695
696   bsize = gst_buffer_get_size (*buf);
697   /* Catch short reads - we don't want any partial atoms */
698   if (G_UNLIKELY (bsize < size)) {
699     GST_WARNING_OBJECT (qtdemux,
700         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
701     gst_buffer_unref (*buf);
702     *buf = NULL;
703     return GST_FLOW_EOS;
704   }
705
706   return flow;
707 }
708
709 #if 1
710 static gboolean
711 gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
712     GstFormat dest_format, gint64 * dest_value)
713 {
714   gboolean res = TRUE;
715   QtDemuxStream *stream = gst_pad_get_element_private (pad);
716   GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
717   gint32 index;
718
719   if (stream->subtype != FOURCC_vide) {
720     res = FALSE;
721     goto done;
722   }
723
724   switch (src_format) {
725     case GST_FORMAT_TIME:
726       switch (dest_format) {
727         case GST_FORMAT_BYTES:{
728           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
729           if (-1 == index)
730             return FALSE;
731
732           *dest_value = stream->samples[index].offset;
733
734           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
735               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
736               GST_TIME_ARGS (src_value), *dest_value);
737           break;
738         }
739         default:
740           res = FALSE;
741           break;
742       }
743       break;
744     case GST_FORMAT_BYTES:
745       switch (dest_format) {
746         case GST_FORMAT_TIME:{
747           index =
748               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
749               stream, src_value);
750
751           if (-1 == index)
752             return FALSE;
753
754           *dest_value =
755               QTSTREAMTIME_TO_GSTTIME (stream,
756               stream->samples[index].timestamp);
757           GST_DEBUG_OBJECT (qtdemux,
758               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
759               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
760           break;
761         }
762         default:
763           res = FALSE;
764           break;
765       }
766       break;
767     default:
768       res = FALSE;
769   }
770
771 done:
772   gst_object_unref (qtdemux);
773
774   return res;
775 }
776 #endif
777
778 static gboolean
779 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
780 {
781   gboolean res = TRUE;
782
783   *duration = GST_CLOCK_TIME_NONE;
784
785   if (qtdemux->duration != 0) {
786     if (qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
787       *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
788     }
789   }
790   return res;
791 }
792
793 static gboolean
794 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
795     GstQuery * query)
796 {
797   gboolean res = FALSE;
798   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
799
800   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
801
802   switch (GST_QUERY_TYPE (query)) {
803     case GST_QUERY_POSITION:{
804       GstFormat fmt;
805
806       gst_query_parse_position (query, &fmt, NULL);
807       if (fmt == GST_FORMAT_TIME
808           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
809         gst_query_set_position (query, GST_FORMAT_TIME,
810             qtdemux->segment.position);
811         res = TRUE;
812       }
813     }
814       break;
815     case GST_QUERY_DURATION:{
816       GstFormat fmt;
817
818       gst_query_parse_duration (query, &fmt, NULL);
819       if (fmt == GST_FORMAT_TIME) {
820         /* First try to query upstream */
821         res = gst_pad_query_default (pad, parent, query);
822         if (!res) {
823           guint64 duration;
824           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
825             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
826             res = TRUE;
827           }
828         }
829       }
830       break;
831     }
832     case GST_QUERY_CONVERT:{
833       GstFormat src_fmt, dest_fmt;
834       gint64 src_value, dest_value = 0;
835
836       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
837
838       res = gst_qtdemux_src_convert (pad,
839           src_fmt, src_value, dest_fmt, &dest_value);
840       if (res) {
841         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
842         res = TRUE;
843       }
844       break;
845     }
846     case GST_QUERY_FORMATS:
847       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
848       res = TRUE;
849       break;
850     case GST_QUERY_SEEKING:{
851       GstFormat fmt;
852       gboolean seekable;
853
854       /* try upstream first */
855       res = gst_pad_query_default (pad, parent, query);
856
857       if (!res) {
858         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
859         if (fmt == GST_FORMAT_TIME) {
860           GstClockTime duration = GST_CLOCK_TIME_NONE;
861
862           gst_qtdemux_get_duration (qtdemux, &duration);
863           seekable = TRUE;
864           if (!qtdemux->pullbased) {
865             GstQuery *q;
866
867             /* we might be able with help from upstream */
868             seekable = FALSE;
869             q = gst_query_new_seeking (GST_FORMAT_BYTES);
870             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
871               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
872               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
873             }
874             gst_query_unref (q);
875           }
876           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
877           res = TRUE;
878         }
879       }
880       break;
881     }
882     case GST_QUERY_SEGMENT:
883     {
884       GstFormat format;
885       gint64 start, stop;
886
887       format = qtdemux->segment.format;
888
889       start =
890           gst_segment_to_stream_time (&qtdemux->segment, format,
891           qtdemux->segment.start);
892       if ((stop = qtdemux->segment.stop) == -1)
893         stop = qtdemux->segment.duration;
894       else
895         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
896
897       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
898       res = TRUE;
899       break;
900     }
901     default:
902       res = gst_pad_query_default (pad, parent, query);
903       break;
904   }
905
906   return res;
907 }
908
909 static void
910 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
911 {
912   if (G_LIKELY (stream->pad)) {
913     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
914         GST_DEBUG_PAD_NAME (stream->pad));
915
916     if (G_UNLIKELY (stream->pending_tags)) {
917       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
918           stream->pending_tags);
919       gst_pad_push_event (stream->pad,
920           gst_event_new_tag (stream->pending_tags));
921 #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
922       /* post message qtdemux tag (for early recive application) */
923       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
924             gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
925                   gst_tag_list_copy (stream->pending_tags)));
926 #endif
927       stream->pending_tags = NULL;
928     }
929
930     if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
931       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
932           qtdemux->tag_list);
933       gst_pad_push_event (stream->pad,
934           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
935       stream->send_global_tags = FALSE;
936     }
937   }
938 }
939
940 /* push event on all source pads; takes ownership of the event */
941 static void
942 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
943 {
944   guint n;
945   gboolean has_valid_stream = FALSE;
946   GstEventType etype = GST_EVENT_TYPE (event);
947
948   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
949       GST_EVENT_TYPE_NAME (event));
950
951   for (n = 0; n < qtdemux->n_streams; n++) {
952     GstPad *pad;
953     QtDemuxStream *stream = qtdemux->streams[n];
954     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
955
956     if ((pad = stream->pad)) {
957       has_valid_stream = TRUE;
958
959       if (etype == GST_EVENT_EOS) {
960         /* let's not send twice */
961         if (stream->sent_eos)
962           continue;
963         stream->sent_eos = TRUE;
964       }
965
966       gst_pad_push_event (pad, gst_event_ref (event));
967     }
968   }
969
970   gst_event_unref (event);
971
972   /* if it is EOS and there are no pads, post an error */
973   if (!has_valid_stream && etype == GST_EVENT_EOS) {
974     gst_qtdemux_post_no_playable_stream_error (qtdemux);
975   }
976 }
977
978 /* push a pending newsegment event, if any from the streaming thread */
979 static void
980 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
981 {
982   if (qtdemux->pending_newsegment) {
983     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
984     qtdemux->pending_newsegment = NULL;
985   }
986 }
987
988 typedef struct
989 {
990   guint64 media_time;
991 } FindData;
992
993 static gint
994 find_func (QtDemuxSample * s1, guint64 * media_time, gpointer user_data)
995 {
996   if (s1->timestamp + s1->pts_offset > *media_time)
997     return 1;
998
999   return -1;
1000 }
1001
1002 /* find the index of the sample that includes the data for @media_time using a
1003  * binary search.  Only to be called in optimized cases of linear search below.
1004  *
1005  * Returns the index of the sample.
1006  */
1007 static guint32
1008 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1009     guint64 media_time)
1010 {
1011   QtDemuxSample *result;
1012   guint32 index;
1013
1014   /* convert media_time to mov format */
1015   media_time =
1016       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1017
1018   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1019       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1020       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1021
1022   if (G_LIKELY (result))
1023     index = result - str->samples;
1024   else
1025     index = 0;
1026
1027   return index;
1028 }
1029
1030
1031
1032 /* find the index of the sample that includes the data for @media_offset using a
1033  * linear search
1034  *
1035  * Returns the index of the sample.
1036  */
1037 static guint32
1038 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1039     QtDemuxStream * str, gint64 media_offset)
1040 {
1041   QtDemuxSample *result = str->samples;
1042   guint32 index = 0;
1043
1044   if (result == NULL || str->n_samples == 0)
1045     return -1;
1046
1047   if (media_offset == result->offset)
1048     return index;
1049
1050   result++;
1051   while (index < str->n_samples - 1) {
1052     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1053       goto parse_failed;
1054
1055     if (media_offset < result->offset)
1056       break;
1057
1058     index++;
1059     result++;
1060   }
1061   return index;
1062
1063   /* ERRORS */
1064 parse_failed:
1065   {
1066     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1067     return -1;
1068   }
1069 }
1070
1071 /* find the index of the sample that includes the data for @media_time using a
1072  * linear search, and keeping in mind that not all samples may have been parsed
1073  * yet.  If possible, it will delegate to binary search.
1074  *
1075  * Returns the index of the sample.
1076  */
1077 static guint32
1078 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1079     GstClockTime media_time)
1080 {
1081   guint32 index = 0;
1082   guint64 mov_time;
1083   QtDemuxSample *sample;
1084
1085   /* convert media_time to mov format */
1086   mov_time =
1087       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1088
1089   sample = str->samples;
1090   if (mov_time == sample->timestamp + sample->pts_offset)
1091     return index;
1092
1093   /* use faster search if requested time in already parsed range */
1094   sample = str->samples + str->stbl_index;
1095   if (str->stbl_index >= 0 &&
1096       mov_time <= (sample->timestamp + sample->pts_offset))
1097     return gst_qtdemux_find_index (qtdemux, str, media_time);
1098
1099   while (index < str->n_samples - 1) {
1100     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1101       goto parse_failed;
1102
1103     sample = str->samples + index + 1;
1104     if (mov_time < (sample->timestamp + sample->pts_offset))
1105       break;
1106
1107     index++;
1108   }
1109   return index;
1110
1111   /* ERRORS */
1112 parse_failed:
1113   {
1114     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1115     return -1;
1116   }
1117 }
1118
1119 /* find the index of the keyframe needed to decode the sample at @index
1120  * of stream @str.
1121  *
1122  * Returns the index of the keyframe.
1123  */
1124 static guint32
1125 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1126     guint32 index)
1127 {
1128   guint32 new_index = index;
1129
1130   if (index >= str->n_samples) {
1131     new_index = str->n_samples;
1132     goto beach;
1133   }
1134
1135   /* all keyframes, return index */
1136   if (str->all_keyframe) {
1137     new_index = index;
1138     goto beach;
1139   }
1140
1141   /* else go back until we have a keyframe */
1142   while (TRUE) {
1143     if (str->samples[new_index].keyframe)
1144       break;
1145
1146     if (new_index == 0)
1147       break;
1148
1149     new_index--;
1150   }
1151
1152 beach:
1153   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index before index %u "
1154       "gave %u", index, new_index);
1155
1156   return new_index;
1157 }
1158
1159 /* find the segment for @time_position for @stream
1160  *
1161  * Returns the index of the segment containing @time_position.
1162  * Returns the last segment and sets the @eos variable to TRUE
1163  * if the time is beyond the end. @eos may be NULL
1164  */
1165 static guint32
1166 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1167     GstClockTime time_position)
1168 {
1169   gint i;
1170   guint32 seg_idx;
1171
1172   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1173       GST_TIME_ARGS (time_position));
1174
1175   seg_idx = -1;
1176   for (i = 0; i < stream->n_segments; i++) {
1177     QtDemuxSegment *segment = &stream->segments[i];
1178
1179     GST_LOG_OBJECT (stream->pad,
1180         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1181         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1182
1183     /* For the last segment we include stop_time in the last segment */
1184     if (i < stream->n_segments - 1) {
1185       if (segment->time <= time_position && time_position < segment->stop_time) {
1186         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1187         seg_idx = i;
1188         break;
1189       }
1190     } else {
1191       /* Last segment always matches */
1192       seg_idx = i;
1193       break;
1194     }
1195   }
1196   return seg_idx;
1197 }
1198
1199 /* move the stream @str to the sample position @index.
1200  *
1201  * Updates @str->sample_index and marks discontinuity if needed.
1202  */
1203 static void
1204 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1205     guint32 index)
1206 {
1207   /* no change needed */
1208   if (index == str->sample_index)
1209     return;
1210
1211   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1212       str->n_samples);
1213
1214   /* position changed, we have a discont */
1215   str->sample_index = index;
1216   str->offset_in_sample = 0;
1217   /* Each time we move in the stream we store the position where we are
1218    * starting from */
1219   str->from_sample = index;
1220   str->discont = TRUE;
1221 }
1222
1223 static void
1224 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1225     gboolean use_sparse, gint64 * key_time, gint64 * key_offset)
1226 {
1227   guint64 min_offset;
1228   gint64 min_byte_offset = -1;
1229   gint n;
1230
1231   min_offset = desired_time;
1232
1233   /* for each stream, find the index of the sample in the segment
1234    * and move back to the previous keyframe. */
1235   for (n = 0; n < qtdemux->n_streams; n++) {
1236     QtDemuxStream *str;
1237     guint32 index, kindex;
1238     guint32 seg_idx;
1239     GstClockTime media_start;
1240     GstClockTime media_time;
1241     GstClockTime seg_time;
1242     QtDemuxSegment *seg;
1243
1244     str = qtdemux->streams[n];
1245
1246     if (str->sparse && !use_sparse)
1247       continue;
1248
1249     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1250     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1251
1252     /* get segment and time in the segment */
1253     seg = &str->segments[seg_idx];
1254     seg_time = desired_time - seg->time;
1255
1256     /* get the media time in the segment */
1257     media_start = seg->media_start + seg_time;
1258
1259     /* get the index of the sample with media time */
1260     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1261     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1262         " at offset %" G_GUINT64_FORMAT,
1263         GST_TIME_ARGS (media_start), index, str->samples[index].offset);
1264
1265     /* find previous keyframe */
1266     kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
1267
1268     /* if the keyframe is at a different position, we need to update the
1269      * requested seek time */
1270     if (index != kindex) {
1271       index = kindex;
1272
1273       /* get timestamp of keyframe */
1274       media_time = QTSAMPLE_DTS (str, &str->samples[kindex]);
1275       GST_DEBUG_OBJECT (qtdemux,
1276           "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1277           G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1278           str->samples[kindex].offset);
1279
1280       /* keyframes in the segment get a chance to change the
1281        * desired_offset. keyframes out of the segment are
1282        * ignored. */
1283       if (media_time >= seg->media_start) {
1284         GstClockTime seg_time;
1285
1286         /* this keyframe is inside the segment, convert back to
1287          * segment time */
1288         seg_time = (media_time - seg->media_start) + seg->time;
1289         if (seg_time < min_offset)
1290           min_offset = seg_time;
1291       }
1292     }
1293
1294     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1295       min_byte_offset = str->samples[index].offset;
1296   }
1297
1298   if (key_time)
1299     *key_time = min_offset;
1300   if (key_offset)
1301     *key_offset = min_byte_offset;
1302 }
1303
1304 static gboolean
1305 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1306     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1307 {
1308   gboolean res;
1309
1310   g_return_val_if_fail (format != NULL, FALSE);
1311   g_return_val_if_fail (cur != NULL, FALSE);
1312   g_return_val_if_fail (stop != NULL, FALSE);
1313
1314   if (*format == GST_FORMAT_TIME)
1315     return TRUE;
1316
1317   res = TRUE;
1318   if (cur_type != GST_SEEK_TYPE_NONE)
1319     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1320   if (res && stop_type != GST_SEEK_TYPE_NONE)
1321     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1322
1323   if (res)
1324     *format = GST_FORMAT_TIME;
1325
1326   return res;
1327 }
1328
1329 /* perform seek in push based mode:
1330    find BYTE position to move to based on time and delegate to upstream
1331 */
1332 static gboolean
1333 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1334 {
1335   gdouble rate;
1336   GstFormat format;
1337   GstSeekFlags flags;
1338   GstSeekType cur_type, stop_type;
1339   gint64 cur, stop, key_cur;
1340   gboolean res;
1341   gint64 byte_cur;
1342   gint64 original_stop;
1343   guint32 seqnum;
1344
1345   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1346
1347   gst_event_parse_seek (event, &rate, &format, &flags,
1348       &cur_type, &cur, &stop_type, &stop);
1349   seqnum = gst_event_get_seqnum (event);
1350
1351   /* only forward streaming and seeking is possible */
1352   if (rate <= 0)
1353     goto unsupported_seek;
1354
1355   /* convert to TIME if needed and possible */
1356   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1357           stop_type, &stop))
1358     goto no_format;
1359
1360   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1361    * the original stop position to use when upstream pushes the new segment
1362    * for this seek */
1363   original_stop = stop;
1364   stop = -1;
1365
1366   /* find reasonable corresponding BYTE position,
1367    * also try to mind about keyframes, since we can not go back a bit for them
1368    * later on */
1369   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, &key_cur, &byte_cur);
1370
1371   if (byte_cur == -1)
1372     goto abort_seek;
1373
1374   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1375       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1376       stop);
1377
1378   GST_OBJECT_LOCK (qtdemux);
1379   qtdemux->seek_offset = byte_cur;
1380   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1381     qtdemux->push_seek_start = cur;
1382   } else {
1383     qtdemux->push_seek_start = key_cur;
1384   }
1385
1386   if (stop_type == GST_SEEK_TYPE_NONE) {
1387     qtdemux->push_seek_stop = qtdemux->segment.stop;
1388   } else {
1389     qtdemux->push_seek_stop = original_stop;
1390   }
1391   GST_OBJECT_UNLOCK (qtdemux);
1392
1393   /* BYTE seek event */
1394   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1395       stop_type, stop);
1396   gst_event_set_seqnum (event, seqnum);
1397   res = gst_pad_push_event (qtdemux->sinkpad, event);
1398
1399   return res;
1400
1401   /* ERRORS */
1402 abort_seek:
1403   {
1404     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1405         "seek aborted.");
1406     return FALSE;
1407   }
1408 unsupported_seek:
1409   {
1410     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1411     return FALSE;
1412   }
1413 no_format:
1414   {
1415     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1416     return FALSE;
1417   }
1418 }
1419
1420 /* perform the seek.
1421  *
1422  * We set all segment_indexes in the streams to unknown and
1423  * adjust the time_position to the desired position. this is enough
1424  * to trigger a segment switch in the streaming thread to start
1425  * streaming from the desired position.
1426  *
1427  * Keyframe seeking is a little more complicated when dealing with
1428  * segments. Ideally we want to move to the previous keyframe in
1429  * the segment but there might not be a keyframe in the segment. In
1430  * fact, none of the segments could contain a keyframe. We take a
1431  * practical approach: seek to the previous keyframe in the segment,
1432  * if there is none, seek to the beginning of the segment.
1433  *
1434  * Called with STREAM_LOCK
1435  */
1436 static gboolean
1437 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1438     guint32 seqnum, GstSeekFlags flags)
1439 {
1440   gint64 desired_offset;
1441   gint n;
1442
1443   desired_offset = segment->position;
1444
1445   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1446       GST_TIME_ARGS (desired_offset));
1447
1448   /* may not have enough fragmented info to do this adjustment,
1449    * and we can't scan (and probably should not) at this time with
1450    * possibly flushing upstream */
1451   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1452     gint64 min_offset;
1453
1454     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, &min_offset, NULL);
1455     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1456         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1457     desired_offset = min_offset;
1458   }
1459
1460   /* and set all streams to the final position */
1461   gst_flow_combiner_reset (qtdemux->flowcombiner);
1462   for (n = 0; n < qtdemux->n_streams; n++) {
1463     QtDemuxStream *stream = qtdemux->streams[n];
1464
1465     stream->time_position = desired_offset;
1466     stream->accumulated_base = 0;
1467     stream->sample_index = -1;
1468     stream->offset_in_sample = 0;
1469     stream->segment_index = -1;
1470     stream->sent_eos = FALSE;
1471     stream->segment_seqnum = seqnum;
1472
1473     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1474       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1475   }
1476   segment->position = desired_offset;
1477   segment->time = desired_offset;
1478   if (segment->rate >= 0) {
1479     segment->start = desired_offset;
1480
1481     /* we stop at the end */
1482     if (segment->stop == -1)
1483       segment->stop = segment->duration;
1484   } else {
1485     segment->stop = desired_offset;
1486   }
1487
1488   if (qtdemux->fragmented)
1489     qtdemux->fragmented_seek_pending = TRUE;
1490
1491   return TRUE;
1492 }
1493
1494 /* do a seek in pull based mode */
1495 static gboolean
1496 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1497 {
1498   gdouble rate;
1499   GstFormat format;
1500   GstSeekFlags flags;
1501   GstSeekType cur_type, stop_type;
1502   gint64 cur, stop;
1503   gboolean flush;
1504   gboolean update;
1505   GstSegment seeksegment;
1506   guint32 seqnum = 0;
1507   GstEvent *flush_event;
1508
1509   if (event) {
1510     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1511
1512     gst_event_parse_seek (event, &rate, &format, &flags,
1513         &cur_type, &cur, &stop_type, &stop);
1514     seqnum = gst_event_get_seqnum (event);
1515
1516     /* we have to have a format as the segment format. Try to convert
1517      * if not. */
1518     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1519             stop_type, &stop))
1520       goto no_format;
1521
1522     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1523   } else {
1524     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1525     flags = 0;
1526   }
1527
1528   flush = flags & GST_SEEK_FLAG_FLUSH;
1529
1530   /* stop streaming, either by flushing or by pausing the task */
1531   if (flush) {
1532     flush_event = gst_event_new_flush_start ();
1533     if (seqnum)
1534       gst_event_set_seqnum (flush_event, seqnum);
1535     /* unlock upstream pull_range */
1536     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1537     /* make sure out loop function exits */
1538     gst_qtdemux_push_event (qtdemux, flush_event);
1539   } else {
1540     /* non flushing seek, pause the task */
1541     gst_pad_pause_task (qtdemux->sinkpad);
1542   }
1543
1544   /* wait for streaming to finish */
1545   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1546
1547   /* copy segment, we need this because we still need the old
1548    * segment when we close the current segment. */
1549   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1550
1551   if (event) {
1552     /* configure the segment with the seek variables */
1553     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1554     gst_segment_do_seek (&seeksegment, rate, format, flags,
1555         cur_type, cur, stop_type, stop, &update);
1556   }
1557
1558   /* now do the seek, this actually never returns FALSE */
1559   gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1560
1561   /* prepare for streaming again */
1562   if (flush) {
1563     flush_event = gst_event_new_flush_stop (TRUE);
1564     if (seqnum)
1565       gst_event_set_seqnum (flush_event, seqnum);
1566
1567     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1568     gst_qtdemux_push_event (qtdemux, flush_event);
1569   }
1570
1571   /* commit the new segment */
1572   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1573
1574   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1575     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1576         qtdemux->segment.format, qtdemux->segment.position);
1577     if (seqnum)
1578       gst_message_set_seqnum (msg, seqnum);
1579     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1580   }
1581
1582   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1583   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1584       qtdemux->sinkpad, NULL);
1585
1586   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1587
1588   return TRUE;
1589
1590   /* ERRORS */
1591 no_format:
1592   {
1593     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1594     return FALSE;
1595   }
1596 }
1597
1598 static gboolean
1599 qtdemux_ensure_index (GstQTDemux * qtdemux)
1600 {
1601   guint i;
1602
1603   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1604
1605   /* Build complete index */
1606   for (i = 0; i < qtdemux->n_streams; i++) {
1607     QtDemuxStream *stream = qtdemux->streams[i];
1608
1609     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1610       goto parse_error;
1611   }
1612   return TRUE;
1613
1614   /* ERRORS */
1615 parse_error:
1616   {
1617     GST_LOG_OBJECT (qtdemux,
1618         "Building complete index of stream %u for seeking failed!", i);
1619     return FALSE;
1620   }
1621 }
1622
1623 static gboolean
1624 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1625     GstEvent * event)
1626 {
1627   gboolean res = TRUE;
1628   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1629
1630   switch (GST_EVENT_TYPE (event)) {
1631     case GST_EVENT_SEEK:
1632     {
1633 #ifndef GST_DISABLE_GST_DEBUG
1634       GstClockTime ts = gst_util_get_timestamp ();
1635 #endif
1636
1637       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1638         /* seek should be handled by upstream, we might need to re-download fragments */
1639         GST_DEBUG_OBJECT (qtdemux,
1640             "let upstream handle seek for fragmented playback");
1641         goto upstream;
1642       }
1643
1644       /* Build complete index for seeking;
1645        * if not a fragmented file at least */
1646       if (!qtdemux->fragmented)
1647         if (!qtdemux_ensure_index (qtdemux))
1648           goto index_failed;
1649 #ifndef GST_DISABLE_GST_DEBUG
1650       ts = gst_util_get_timestamp () - ts;
1651       GST_INFO_OBJECT (qtdemux,
1652           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1653 #endif
1654     }
1655       if (qtdemux->pullbased) {
1656         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1657       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1658         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1659         res = TRUE;
1660       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1661           && !qtdemux->fragmented) {
1662         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1663       } else {
1664         GST_DEBUG_OBJECT (qtdemux,
1665             "ignoring seek in push mode in current state");
1666         res = FALSE;
1667       }
1668       gst_event_unref (event);
1669       break;
1670     case GST_EVENT_QOS:
1671     case GST_EVENT_NAVIGATION:
1672       res = FALSE;
1673       gst_event_unref (event);
1674       break;
1675     default:
1676     upstream:
1677       res = gst_pad_event_default (pad, parent, event);
1678       break;
1679   }
1680
1681 done:
1682   return res;
1683
1684   /* ERRORS */
1685 index_failed:
1686   {
1687     GST_ERROR_OBJECT (qtdemux, "Index failed");
1688     gst_event_unref (event);
1689     res = FALSE;
1690     goto done;
1691   }
1692 }
1693
1694 /* stream/index return sample that is min/max w.r.t. byte position,
1695  * time is min/max w.r.t. time of samples,
1696  * the latter need not be time of the former sample */
1697 static void
1698 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1699     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1700 {
1701   gint i, n, index;
1702   gint64 time, min_time;
1703   QtDemuxStream *stream;
1704
1705   min_time = -1;
1706   stream = NULL;
1707   index = -1;
1708
1709   for (n = 0; n < qtdemux->n_streams; ++n) {
1710     QtDemuxStream *str;
1711     gint inc;
1712     gboolean set_sample;
1713
1714     str = qtdemux->streams[n];
1715     set_sample = !set;
1716
1717     if (fw) {
1718       i = 0;
1719       inc = 1;
1720     } else {
1721       i = str->n_samples - 1;
1722       inc = -1;
1723     }
1724
1725     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1726       if (str->samples[i].size == 0)
1727         continue;
1728
1729       if (fw && (str->samples[i].offset < byte_pos))
1730         continue;
1731
1732       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1733         continue;
1734
1735       /* move stream to first available sample */
1736       if (set) {
1737         gst_qtdemux_move_stream (qtdemux, str, i);
1738         set_sample = TRUE;
1739       }
1740
1741       /* avoid index from sparse streams since they might be far away */
1742       if (!str->sparse) {
1743         /* determine min/max time */
1744         time = QTSAMPLE_PTS (str, &str->samples[i]);
1745         if (min_time == -1 || (!fw && time > min_time) ||
1746             (fw && time < min_time)) {
1747           min_time = time;
1748         }
1749
1750         /* determine stream with leading sample, to get its position */
1751         if (!stream ||
1752             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1753             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1754           stream = str;
1755           index = i;
1756         }
1757       }
1758       break;
1759     }
1760
1761     /* no sample for this stream, mark eos */
1762     if (!set_sample)
1763       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1764   }
1765
1766   if (_time)
1767     *_time = min_time;
1768   if (_stream)
1769     *_stream = stream;
1770   if (_index)
1771     *_index = index;
1772 }
1773
1774 static QtDemuxStream *
1775 _create_stream (void)
1776 {
1777   QtDemuxStream *stream;
1778
1779   stream = g_new0 (QtDemuxStream, 1);
1780   /* new streams always need a discont */
1781   stream->discont = TRUE;
1782   /* we enable clipping for raw audio/video streams */
1783   stream->need_clip = FALSE;
1784   stream->need_process = FALSE;
1785   stream->segment_index = -1;
1786   stream->time_position = 0;
1787   stream->sample_index = -1;
1788   stream->offset_in_sample = 0;
1789   stream->new_stream = TRUE;
1790   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1791   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1792   stream->protected = FALSE;
1793   stream->protection_scheme_type = 0;
1794   stream->protection_scheme_version = 0;
1795   stream->protection_scheme_info = NULL;
1796   g_queue_init (&stream->protection_scheme_event_queue);
1797   return stream;
1798 }
1799
1800 static gboolean
1801 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1802 {
1803   GstStructure *structure;
1804   const gchar *variant;
1805   const GstCaps *mediacaps = NULL;
1806
1807   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1808
1809   structure = gst_caps_get_structure (caps, 0);
1810   variant = gst_structure_get_string (structure, "variant");
1811
1812   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1813     QtDemuxStream *stream;
1814     const GValue *value;
1815
1816     demux->fragmented = TRUE;
1817     demux->mss_mode = TRUE;
1818
1819     if (demux->n_streams > 1) {
1820       /* can't do this, we can only renegotiate for another mss format */
1821       return FALSE;
1822     }
1823
1824     value = gst_structure_get_value (structure, "media-caps");
1825     /* create stream */
1826     if (value) {
1827       const GValue *timescale_v;
1828
1829       /* TODO update when stream changes during playback */
1830
1831       if (demux->n_streams == 0) {
1832         stream = _create_stream ();
1833         demux->streams[demux->n_streams] = stream;
1834         demux->n_streams = 1;
1835       } else {
1836         stream = demux->streams[0];
1837       }
1838
1839       timescale_v = gst_structure_get_value (structure, "timescale");
1840       if (timescale_v) {
1841         stream->timescale = g_value_get_uint64 (timescale_v);
1842       } else {
1843         /* default mss timescale */
1844         stream->timescale = 10000000;
1845       }
1846       demux->timescale = stream->timescale;
1847
1848       mediacaps = gst_value_get_caps (value);
1849       if (!stream->caps || !gst_caps_is_equal_fixed (mediacaps, stream->caps)) {
1850         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1851             mediacaps);
1852         stream->new_caps = TRUE;
1853       }
1854       gst_caps_replace (&stream->caps, (GstCaps *) mediacaps);
1855       structure = gst_caps_get_structure (mediacaps, 0);
1856       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1857         stream->subtype = FOURCC_vide;
1858
1859         gst_structure_get_int (structure, "width", &stream->width);
1860         gst_structure_get_int (structure, "height", &stream->height);
1861         gst_structure_get_fraction (structure, "framerate", &stream->fps_n,
1862             &stream->fps_d);
1863       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1864         gint rate = 0;
1865         stream->subtype = FOURCC_soun;
1866         gst_structure_get_int (structure, "channels", &stream->n_channels);
1867         gst_structure_get_int (structure, "rate", &rate);
1868         stream->rate = rate;
1869       }
1870     }
1871     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1872   } else {
1873     demux->mss_mode = FALSE;
1874   }
1875
1876   return TRUE;
1877 }
1878
1879 static void
1880 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1881 {
1882   gint n;
1883
1884   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1885   gst_pad_stop_task (qtdemux->sinkpad);
1886
1887   if (hard || qtdemux->upstream_format_is_time) {
1888     qtdemux->state = QTDEMUX_STATE_INITIAL;
1889     qtdemux->neededbytes = 16;
1890     qtdemux->todrop = 0;
1891     qtdemux->pullbased = FALSE;
1892     qtdemux->posted_redirect = FALSE;
1893     qtdemux->first_mdat = -1;
1894     qtdemux->header_size = 0;
1895     qtdemux->mdatoffset = -1;
1896     qtdemux->restoredata_offset = -1;
1897     if (qtdemux->mdatbuffer)
1898       gst_buffer_unref (qtdemux->mdatbuffer);
1899     if (qtdemux->restoredata_buffer)
1900       gst_buffer_unref (qtdemux->restoredata_buffer);
1901     qtdemux->mdatbuffer = NULL;
1902     qtdemux->restoredata_buffer = NULL;
1903     qtdemux->mdatleft = 0;
1904     if (qtdemux->comp_brands)
1905       gst_buffer_unref (qtdemux->comp_brands);
1906     qtdemux->comp_brands = NULL;
1907     qtdemux->last_moov_offset = -1;
1908     if (qtdemux->moov_node)
1909       g_node_destroy (qtdemux->moov_node);
1910     qtdemux->moov_node = NULL;
1911     qtdemux->moov_node_compressed = NULL;
1912     if (qtdemux->tag_list)
1913       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1914     qtdemux->tag_list = NULL;
1915 #if 0
1916     if (qtdemux->element_index)
1917       gst_object_unref (qtdemux->element_index);
1918     qtdemux->element_index = NULL;
1919 #endif
1920     qtdemux->major_brand = 0;
1921     if (qtdemux->pending_newsegment)
1922       gst_event_unref (qtdemux->pending_newsegment);
1923     qtdemux->pending_newsegment = NULL;
1924     qtdemux->upstream_format_is_time = FALSE;
1925     qtdemux->upstream_seekable = FALSE;
1926     qtdemux->upstream_size = 0;
1927
1928     qtdemux->fragment_start = -1;
1929     qtdemux->fragment_start_offset = -1;
1930     qtdemux->duration = 0;
1931     qtdemux->moof_offset = 0;
1932     qtdemux->chapters_track_id = 0;
1933     qtdemux->have_group_id = FALSE;
1934     qtdemux->group_id = G_MAXUINT;
1935
1936     if (qtdemux->protection_system_ids) {
1937       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
1938       qtdemux->protection_system_ids = NULL;
1939     }
1940     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
1941         NULL);
1942     g_queue_clear (&qtdemux->protection_event_queue);
1943   }
1944   qtdemux->offset = 0;
1945   gst_adapter_clear (qtdemux->adapter);
1946   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
1947
1948   if (hard) {
1949     for (n = 0; n < qtdemux->n_streams; n++) {
1950       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
1951       qtdemux->streams[n] = NULL;
1952     }
1953     qtdemux->n_streams = 0;
1954     qtdemux->n_video_streams = 0;
1955     qtdemux->n_audio_streams = 0;
1956     qtdemux->n_sub_streams = 0;
1957     qtdemux->exposed = FALSE;
1958     qtdemux->fragmented = FALSE;
1959     qtdemux->mss_mode = FALSE;
1960     gst_caps_replace (&qtdemux->media_caps, NULL);
1961     qtdemux->timescale = 0;
1962     qtdemux->got_moov = FALSE;
1963   } else if (qtdemux->mss_mode) {
1964     gst_flow_combiner_reset (qtdemux->flowcombiner);
1965     for (n = 0; n < qtdemux->n_streams; n++)
1966       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
1967   } else {
1968     gst_flow_combiner_reset (qtdemux->flowcombiner);
1969     for (n = 0; n < qtdemux->n_streams; n++) {
1970       qtdemux->streams[n]->sent_eos = FALSE;
1971       qtdemux->streams[n]->segment_seqnum = 0;
1972       qtdemux->streams[n]->time_position = 0;
1973       qtdemux->streams[n]->accumulated_base = 0;
1974     }
1975   }
1976 }
1977
1978 static gboolean
1979 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
1980     GstEvent * event)
1981 {
1982   GstQTDemux *demux = GST_QTDEMUX (parent);
1983   gboolean res = TRUE;
1984
1985   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
1986
1987   switch (GST_EVENT_TYPE (event)) {
1988     case GST_EVENT_SEGMENT:
1989     {
1990       gint64 offset = 0;
1991       QtDemuxStream *stream;
1992       gint idx;
1993       GstSegment segment;
1994       GstEvent *segment_event;
1995
1996       /* some debug output */
1997       gst_event_copy_segment (event, &segment);
1998       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
1999           &segment);
2000
2001       if (segment.format == GST_FORMAT_TIME) {
2002         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2003         gst_event_replace (&demux->pending_newsegment, event);
2004         demux->upstream_format_is_time = TRUE;
2005       } else {
2006         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2007             "not in time format");
2008
2009         /* chain will send initial newsegment after pads have been added */
2010         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2011           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2012           goto exit;
2013         }
2014       }
2015
2016       /* check if this matches a time seek we received previously
2017        * FIXME for backwards compatibility reasons we use the
2018        * seek_offset here to compare. In the future we might want to
2019        * change this to use the seqnum as it uniquely should identify
2020        * the segment that corresponds to the seek. */
2021       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2022           ", received segment offset %" G_GINT64_FORMAT,
2023           demux->seek_offset, segment.start);
2024       if (segment.format == GST_FORMAT_BYTES
2025           && demux->seek_offset == segment.start) {
2026         GST_OBJECT_LOCK (demux);
2027         offset = segment.start;
2028
2029         segment.format = GST_FORMAT_TIME;
2030         segment.start = demux->push_seek_start;
2031         segment.stop = demux->push_seek_stop;
2032         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2033             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2034             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2035         GST_OBJECT_UNLOCK (demux);
2036       }
2037
2038       /* we only expect a BYTE segment, e.g. following a seek */
2039       if (segment.format == GST_FORMAT_BYTES) {
2040         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2041           offset = segment.start;
2042
2043           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2044               NULL, (gint64 *) & segment.start);
2045           if ((gint64) segment.start < 0)
2046             segment.start = 0;
2047         }
2048         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2049           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2050               NULL, (gint64 *) & segment.stop);
2051           /* keyframe seeking should already arrange for start >= stop,
2052            * but make sure in other rare cases */
2053           segment.stop = MAX (segment.stop, segment.start);
2054         }
2055       } else if (segment.format == GST_FORMAT_TIME) {
2056         /* push all data on the adapter before starting this
2057          * new segment */
2058         gst_qtdemux_process_adapter (demux, TRUE);
2059       } else {
2060         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2061         goto exit;
2062       }
2063
2064       /* accept upstream's notion of segment and distribute along */
2065       segment.format = GST_FORMAT_TIME;
2066       segment.position = segment.time = segment.start;
2067       segment.duration = demux->segment.duration;
2068       segment.base = gst_segment_to_running_time (&demux->segment,
2069           GST_FORMAT_TIME, demux->segment.position);
2070
2071       gst_segment_copy_into (&segment, &demux->segment);
2072       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2073       segment_event = gst_event_new_segment (&segment);
2074       gst_event_set_seqnum (segment_event, gst_event_get_seqnum (event));
2075       gst_qtdemux_push_event (demux, segment_event);
2076
2077       /* clear leftover in current segment, if any */
2078       gst_adapter_clear (demux->adapter);
2079
2080       /* set up streaming thread */
2081       demux->offset = offset;
2082       if (demux->upstream_format_is_time) {
2083         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2084             "set values to restart reading from a new atom");
2085         demux->neededbytes = 16;
2086         demux->todrop = 0;
2087       } else {
2088         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2089             NULL);
2090         if (stream) {
2091           demux->todrop = stream->samples[idx].offset - offset;
2092           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2093         } else {
2094           /* set up for EOS */
2095           demux->neededbytes = -1;
2096           demux->todrop = 0;
2097         }
2098       }
2099     exit:
2100       gst_event_unref (event);
2101       res = TRUE;
2102       goto drop;
2103     }
2104     case GST_EVENT_FLUSH_STOP:
2105     {
2106       guint64 dur;
2107
2108       dur = demux->segment.duration;
2109       gst_qtdemux_reset (demux, FALSE);
2110       demux->segment.duration = dur;
2111       break;
2112     }
2113     case GST_EVENT_EOS:
2114       /* If we are in push mode, and get an EOS before we've seen any streams,
2115        * then error out - we have nowhere to send the EOS */
2116       if (!demux->pullbased) {
2117         gint i;
2118         gboolean has_valid_stream = FALSE;
2119         for (i = 0; i < demux->n_streams; i++) {
2120           if (demux->streams[i]->pad != NULL) {
2121             has_valid_stream = TRUE;
2122             break;
2123           }
2124         }
2125         if (!has_valid_stream)
2126           gst_qtdemux_post_no_playable_stream_error (demux);
2127         else {
2128           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2129               (guint) gst_adapter_available (demux->adapter));
2130           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2131             res = FALSE;
2132           }
2133         }
2134       }
2135       break;
2136     case GST_EVENT_CAPS:{
2137       GstCaps *caps = NULL;
2138
2139       gst_event_parse_caps (event, &caps);
2140       gst_qtdemux_setcaps (demux, caps);
2141       res = TRUE;
2142       gst_event_unref (event);
2143       goto drop;
2144     }
2145     case GST_EVENT_PROTECTION:
2146     {
2147       const gchar *system_id = NULL;
2148
2149       gst_event_parse_protection (event, &system_id, NULL, NULL);
2150       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2151           system_id);
2152       gst_qtdemux_append_protection_system_id (demux, system_id);
2153       /* save the event for later, for source pads that have not been created */
2154       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2155       /* send it to all pads that already exist */
2156       gst_qtdemux_push_event (demux, event);
2157       res = TRUE;
2158       goto drop;
2159     }
2160     default:
2161       break;
2162   }
2163
2164   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2165
2166 drop:
2167   return res;
2168 }
2169
2170 #if 0
2171 static void
2172 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2173 {
2174   GstQTDemux *demux = GST_QTDEMUX (element);
2175
2176   GST_OBJECT_LOCK (demux);
2177   if (demux->element_index)
2178     gst_object_unref (demux->element_index);
2179   if (index) {
2180     demux->element_index = gst_object_ref (index);
2181   } else {
2182     demux->element_index = NULL;
2183   }
2184   GST_OBJECT_UNLOCK (demux);
2185   /* object lock might be taken again */
2186   if (index)
2187     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2188   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2189       demux->element_index, demux->index_id);
2190 }
2191
2192 static GstIndex *
2193 gst_qtdemux_get_index (GstElement * element)
2194 {
2195   GstIndex *result = NULL;
2196   GstQTDemux *demux = GST_QTDEMUX (element);
2197
2198   GST_OBJECT_LOCK (demux);
2199   if (demux->element_index)
2200     result = gst_object_ref (demux->element_index);
2201   GST_OBJECT_UNLOCK (demux);
2202
2203   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2204
2205   return result;
2206 }
2207 #endif
2208
2209 static void
2210 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2211 {
2212   g_free ((gpointer) stream->stco.data);
2213   stream->stco.data = NULL;
2214   g_free ((gpointer) stream->stsz.data);
2215   stream->stsz.data = NULL;
2216   g_free ((gpointer) stream->stsc.data);
2217   stream->stsc.data = NULL;
2218   g_free ((gpointer) stream->stts.data);
2219   stream->stts.data = NULL;
2220   g_free ((gpointer) stream->stss.data);
2221   stream->stss.data = NULL;
2222   g_free ((gpointer) stream->stps.data);
2223   stream->stps.data = NULL;
2224   g_free ((gpointer) stream->ctts.data);
2225   stream->ctts.data = NULL;
2226 }
2227
2228 static void
2229 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2230     QtDemuxStream * stream)
2231 {
2232   g_free (stream->segments);
2233   stream->segments = NULL;
2234   stream->segment_index = -1;
2235   stream->accumulated_base = 0;
2236 }
2237
2238 static void
2239 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2240     QtDemuxStream * stream)
2241 {
2242   g_free (stream->samples);
2243   stream->samples = NULL;
2244   gst_qtdemux_stbl_free (stream);
2245
2246   /* fragments */
2247   g_free (stream->ra_entries);
2248   stream->ra_entries = NULL;
2249   stream->n_ra_entries = 0;
2250
2251   stream->sample_index = -1;
2252   stream->stbl_index = -1;
2253   stream->n_samples = 0;
2254   stream->time_position = 0;
2255 }
2256
2257 static void
2258 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2259 {
2260   if (stream->allocator)
2261     gst_object_unref (stream->allocator);
2262   while (stream->buffers) {
2263     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2264     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2265   }
2266   if (stream->rgb8_palette) {
2267     gst_memory_unref (stream->rgb8_palette);
2268     stream->rgb8_palette = NULL;
2269   }
2270
2271   if (stream->pending_tags)
2272     gst_tag_list_unref (stream->pending_tags);
2273   stream->pending_tags = NULL;
2274   g_free (stream->redirect_uri);
2275   stream->redirect_uri = NULL;
2276   stream->sent_eos = FALSE;
2277   stream->sparse = FALSE;
2278   stream->protected = FALSE;
2279   if (stream->protection_scheme_info) {
2280     if (stream->protection_scheme_type == FOURCC_cenc) {
2281       QtDemuxCencSampleSetInfo *info =
2282           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2283       if (info->default_properties)
2284         gst_structure_free (info->default_properties);
2285       if (info->crypto_info)
2286         g_ptr_array_free (info->crypto_info, TRUE);
2287     }
2288     g_free (stream->protection_scheme_info);
2289     stream->protection_scheme_info = NULL;
2290   }
2291   stream->protection_scheme_type = 0;
2292   stream->protection_scheme_version = 0;
2293   g_queue_foreach (&stream->protection_scheme_event_queue,
2294       (GFunc) gst_event_unref, NULL);
2295   g_queue_clear (&stream->protection_scheme_event_queue);
2296   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2297   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2298 }
2299
2300 static void
2301 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2302 {
2303   gst_qtdemux_stream_clear (qtdemux, stream);
2304   if (stream->caps)
2305     gst_caps_unref (stream->caps);
2306   stream->caps = NULL;
2307   if (stream->pad) {
2308     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2309     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2310   }
2311   g_free (stream);
2312 }
2313
2314 static void
2315 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2316 {
2317   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2318
2319   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2320   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2321   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2322   qtdemux->n_streams--;
2323 }
2324
2325 static GstStateChangeReturn
2326 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2327 {
2328   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2329   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2330
2331   switch (transition) {
2332     case GST_STATE_CHANGE_PAUSED_TO_READY:
2333       break;
2334     default:
2335       break;
2336   }
2337
2338   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2339
2340   switch (transition) {
2341     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2342       gst_qtdemux_reset (qtdemux, TRUE);
2343       break;
2344     }
2345     default:
2346       break;
2347   }
2348
2349   return result;
2350 }
2351
2352 static void
2353 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2354 {
2355   /* counts as header data */
2356   qtdemux->header_size += length;
2357
2358   /* only consider at least a sufficiently complete ftyp atom */
2359   if (length >= 20) {
2360     GstBuffer *buf;
2361
2362     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2363     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2364         GST_FOURCC_ARGS (qtdemux->major_brand));
2365     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2366     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2367   }
2368 }
2369
2370 static void
2371 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2372     GstTagList * xmptaglist)
2373 {
2374   /* Strip out bogus fields */
2375   if (xmptaglist) {
2376     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2377       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2378       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2379     } else {
2380       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2381     }
2382
2383     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2384
2385     /* prioritize native tags using _KEEP mode */
2386     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2387     gst_tag_list_unref (xmptaglist);
2388   }
2389 }
2390
2391 static void
2392 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2393 {
2394   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2395     0x97, 0xA9, 0x42, 0xE8,
2396     0x9C, 0x71, 0x99, 0x94,
2397     0x91, 0xE3, 0xAF, 0xAC
2398   };
2399   static const guint8 playready_uuid[] = {
2400     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2401     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2402   };
2403   guint offset;
2404
2405   /* counts as header data */
2406   qtdemux->header_size += length;
2407
2408   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2409
2410   if (length <= offset + 16) {
2411     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2412     return;
2413   }
2414
2415   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2416     GstBuffer *buf;
2417     GstTagList *taglist;
2418
2419     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2420         length - offset - 16, NULL);
2421     taglist = gst_tag_list_from_xmp_buffer (buf);
2422     gst_buffer_unref (buf);
2423
2424     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2425
2426   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2427     int len;
2428     const gunichar2 *s_utf16;
2429     char *contents;
2430
2431     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2432     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2433     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2434     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2435
2436     g_free (contents);
2437
2438     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2439         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2440         (NULL));
2441   } else {
2442     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2443         GST_READ_UINT32_LE (buffer + offset),
2444         GST_READ_UINT32_LE (buffer + offset + 4),
2445         GST_READ_UINT32_LE (buffer + offset + 8),
2446         GST_READ_UINT32_LE (buffer + offset + 12));
2447   }
2448 }
2449
2450 static void
2451 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2452 {
2453   GstSidxParser sidx_parser;
2454   GstIsoffParserResult res;
2455   guint consumed;
2456
2457   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2458
2459   res =
2460       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2461       &consumed);
2462   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2463   if (res == GST_ISOFF_QT_PARSER_DONE) {
2464     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2465   }
2466   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2467 }
2468
2469 /* caller verifies at least 8 bytes in buf */
2470 static void
2471 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2472     guint64 * plength, guint32 * pfourcc)
2473 {
2474   guint64 length;
2475   guint32 fourcc;
2476
2477   length = QT_UINT32 (data);
2478   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2479   fourcc = QT_FOURCC (data + 4);
2480   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2481
2482   if (length == 0) {
2483     length = G_MAXUINT64;
2484   } else if (length == 1 && size >= 16) {
2485     /* this means we have an extended size, which is the 64 bit value of
2486      * the next 8 bytes */
2487     length = QT_UINT64 (data + 8);
2488     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2489   }
2490
2491   if (plength)
2492     *plength = length;
2493   if (pfourcc)
2494     *pfourcc = fourcc;
2495 }
2496
2497 static gboolean
2498 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2499 {
2500   guint32 version = 0;
2501   GstClockTime duration = 0;
2502
2503   if (!gst_byte_reader_get_uint32_be (br, &version))
2504     goto failed;
2505
2506   version >>= 24;
2507   if (version == 1) {
2508     if (!gst_byte_reader_get_uint64_be (br, &duration))
2509       goto failed;
2510   } else {
2511     guint32 dur = 0;
2512
2513     if (!gst_byte_reader_get_uint32_be (br, &dur))
2514       goto failed;
2515     duration = dur;
2516   }
2517
2518   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2519   qtdemux->duration = duration;
2520
2521   return TRUE;
2522
2523 failed:
2524   {
2525     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2526     return FALSE;
2527   }
2528 }
2529
2530 static gboolean
2531 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2532     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2533 {
2534   if (!stream->parsed_trex && qtdemux->moov_node) {
2535     GNode *mvex, *trex;
2536     GstByteReader trex_data;
2537
2538     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2539     if (mvex) {
2540       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2541           &trex_data);
2542       while (trex) {
2543         guint32 id = 0, dur = 0, size = 0, flags = 0, dummy = 0;
2544
2545         /* skip version/flags */
2546         if (!gst_byte_reader_skip (&trex_data, 4))
2547           goto next;
2548         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2549           goto next;
2550         if (id != stream->track_id)
2551           goto next;
2552         /* sample description index; ignore */
2553         if (!gst_byte_reader_get_uint32_be (&trex_data, &dummy))
2554           goto next;
2555         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2556           goto next;
2557         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2558           goto next;
2559         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2560           goto next;
2561
2562         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2563             "duration %d,  size %d, flags 0x%x", stream->track_id,
2564             dur, size, flags);
2565
2566         stream->parsed_trex = TRUE;
2567         stream->def_sample_duration = dur;
2568         stream->def_sample_size = size;
2569         stream->def_sample_flags = flags;
2570
2571       next:
2572         /* iterate all siblings */
2573         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2574             &trex_data);
2575       }
2576     }
2577   }
2578
2579   *ds_duration = stream->def_sample_duration;
2580   *ds_size = stream->def_sample_size;
2581   *ds_flags = stream->def_sample_flags;
2582
2583   /* even then, above values are better than random ... */
2584   if (G_UNLIKELY (!stream->parsed_trex)) {
2585     GST_WARNING_OBJECT (qtdemux,
2586         "failed to find fragment defaults for stream %d", stream->track_id);
2587     return FALSE;
2588   }
2589
2590   return TRUE;
2591 }
2592
2593 /* This method should be called whenever a more accurate duration might
2594  * have been found. It will update all relevant variables if/where needed
2595  */
2596 static void
2597 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
2598 {
2599   guint i;
2600   guint64 movdur;
2601   GstClockTime prevdur;
2602
2603   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
2604
2605   if (movdur > qtdemux->duration) {
2606     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
2607     GST_DEBUG_OBJECT (qtdemux,
2608         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
2609         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
2610     qtdemux->duration = movdur;
2611     GST_DEBUG_OBJECT (qtdemux,
2612         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
2613         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
2614         GST_TIME_ARGS (qtdemux->segment.stop));
2615     if (qtdemux->segment.duration == prevdur) {
2616       /* If the current segment has duration/stop identical to previous duration
2617        * update them also (because they were set at that point in time with
2618        * the wrong duration */
2619       /* We convert the value *from* the timescale version to avoid rounding errors */
2620       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
2621       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
2622       qtdemux->segment.duration = fixeddur;
2623       qtdemux->segment.stop = fixeddur;
2624     }
2625   }
2626   for (i = 0; i < qtdemux->n_streams; i++) {
2627     QtDemuxStream *stream = qtdemux->streams[i];
2628     if (stream) {
2629       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
2630       if (movdur > stream->duration) {
2631         GST_DEBUG_OBJECT (qtdemux,
2632             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
2633             GST_TIME_ARGS (duration));
2634         stream->duration = movdur;
2635         if (stream->dummy_segment) {
2636           /* Update all dummy values to new duration */
2637           stream->segments[0].stop_time = duration;
2638           stream->segments[0].duration = duration;
2639           stream->segments[0].media_stop = duration;
2640         }
2641       }
2642     }
2643   }
2644 }
2645
2646 static gboolean
2647 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
2648     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
2649     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
2650     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts)
2651 {
2652   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
2653   guint64 timestamp;
2654   gint32 data_offset = 0;
2655   guint32 flags = 0, first_flags = 0, samples_count = 0;
2656   gint i;
2657   guint8 *data;
2658   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
2659   QtDemuxSample *sample;
2660   gboolean ismv = FALSE;
2661
2662   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
2663       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
2664       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
2665       d_sample_size, d_sample_flags, *base_offset, decode_ts);
2666
2667   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
2668     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
2669     return TRUE;
2670   }
2671
2672   /* presence of stss or not can't really tell us much,
2673    * and flags and so on tend to be marginally reliable in these files */
2674   if (stream->subtype == FOURCC_soun) {
2675     GST_DEBUG_OBJECT (qtdemux,
2676         "sound track in fragmented file; marking all keyframes");
2677     stream->all_keyframe = TRUE;
2678   }
2679
2680   if (!gst_byte_reader_skip (trun, 1) ||
2681       !gst_byte_reader_get_uint24_be (trun, &flags))
2682     goto fail;
2683
2684   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
2685     goto fail;
2686
2687   if (flags & TR_DATA_OFFSET) {
2688     /* note this is really signed */
2689     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
2690       goto fail;
2691     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
2692     /* default base offset = first byte of moof */
2693     if (*base_offset == -1) {
2694       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
2695       *base_offset = moof_offset;
2696     }
2697     *running_offset = *base_offset + data_offset;
2698   } else {
2699     /* if no offset at all, that would mean data starts at moof start,
2700      * which is a bit wrong and is ismv crappy way, so compensate
2701      * assuming data is in mdat following moof */
2702     if (*base_offset == -1) {
2703       *base_offset = moof_offset + moof_length + 8;
2704       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
2705       ismv = TRUE;
2706     }
2707     if (*running_offset == -1)
2708       *running_offset = *base_offset;
2709   }
2710
2711   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
2712       *running_offset);
2713   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
2714       data_offset, flags, samples_count);
2715
2716   if (flags & TR_FIRST_SAMPLE_FLAGS) {
2717     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
2718       GST_DEBUG_OBJECT (qtdemux,
2719           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
2720       flags ^= TR_FIRST_SAMPLE_FLAGS;
2721     } else {
2722       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
2723         goto fail;
2724       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
2725     }
2726   }
2727
2728   /* FIXME ? spec says other bits should also be checked to determine
2729    * entry size (and prefix size for that matter) */
2730   entry_size = 0;
2731   dur_offset = size_offset = 0;
2732   if (flags & TR_SAMPLE_DURATION) {
2733     GST_LOG_OBJECT (qtdemux, "entry duration present");
2734     dur_offset = entry_size;
2735     entry_size += 4;
2736   }
2737   if (flags & TR_SAMPLE_SIZE) {
2738     GST_LOG_OBJECT (qtdemux, "entry size present");
2739     size_offset = entry_size;
2740     entry_size += 4;
2741   }
2742   if (flags & TR_SAMPLE_FLAGS) {
2743     GST_LOG_OBJECT (qtdemux, "entry flags present");
2744     flags_offset = entry_size;
2745     entry_size += 4;
2746   }
2747   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2748     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
2749     ct_offset = entry_size;
2750     entry_size += 4;
2751   }
2752
2753   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
2754     goto fail;
2755   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
2756
2757   if (stream->n_samples + samples_count >=
2758       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
2759     goto index_too_big;
2760
2761   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
2762       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
2763       (stream->n_samples + samples_count) *
2764       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
2765
2766   /* create a new array of samples if it's the first sample parsed */
2767   if (stream->n_samples == 0) {
2768     g_assert (stream->samples == NULL);
2769     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
2770     /* or try to reallocate it with space enough to insert the new samples */
2771   } else
2772     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
2773         stream->n_samples + samples_count);
2774   if (stream->samples == NULL)
2775     goto out_of_memory;
2776
2777   if (qtdemux->fragment_start != -1) {
2778     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
2779     qtdemux->fragment_start = -1;
2780   } else {
2781     if (stream->n_samples == 0) {
2782       if (decode_ts > 0) {
2783         timestamp = decode_ts;
2784       } else if (stream->pending_seek != NULL) {
2785         /* if we don't have a timestamp from a tfdt box, we'll use the one
2786          * from the mfra seek table */
2787         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
2788             GST_TIME_ARGS (stream->pending_seek->ts));
2789
2790         /* FIXME: this is not fully correct, the timestamp refers to the random
2791          * access sample refered to in the tfra entry, which may not necessarily
2792          * be the first sample in the tfrag/trun (but hopefully/usually is) */
2793         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
2794       } else {
2795         timestamp = 0;
2796       }
2797
2798       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2799       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
2800           GST_TIME_ARGS (gst_ts));
2801     } else {
2802       /* subsequent fragments extend stream */
2803       timestamp =
2804           stream->samples[stream->n_samples - 1].timestamp +
2805           stream->samples[stream->n_samples - 1].duration;
2806
2807       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
2808       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
2809           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
2810     }
2811   }
2812
2813   sample = stream->samples + stream->n_samples;
2814   for (i = 0; i < samples_count; i++) {
2815     guint32 dur, size, sflags, ct;
2816
2817     /* first read sample data */
2818     if (flags & TR_SAMPLE_DURATION) {
2819       dur = QT_UINT32 (data + dur_offset);
2820     } else {
2821       dur = d_sample_duration;
2822     }
2823     if (flags & TR_SAMPLE_SIZE) {
2824       size = QT_UINT32 (data + size_offset);
2825     } else {
2826       size = d_sample_size;
2827     }
2828     if (flags & TR_FIRST_SAMPLE_FLAGS) {
2829       if (i == 0) {
2830         sflags = first_flags;
2831       } else {
2832         sflags = d_sample_flags;
2833       }
2834     } else if (flags & TR_SAMPLE_FLAGS) {
2835       sflags = QT_UINT32 (data + flags_offset);
2836     } else {
2837       sflags = d_sample_flags;
2838     }
2839     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
2840       ct = QT_UINT32 (data + ct_offset);
2841     } else {
2842       ct = 0;
2843     }
2844     data += entry_size;
2845
2846     /* fill the sample information */
2847     sample->offset = *running_offset;
2848     sample->pts_offset = ct;
2849     sample->size = size;
2850     sample->timestamp = timestamp;
2851     sample->duration = dur;
2852     /* sample-is-difference-sample */
2853     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
2854      * now idea how it relates to bitfield other than massive LE/BE confusion */
2855     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
2856     *running_offset += size;
2857     timestamp += dur;
2858     sample++;
2859   }
2860
2861   /* Update total duration if needed */
2862   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
2863
2864   stream->n_samples += samples_count;
2865
2866   if (stream->pending_seek != NULL)
2867     stream->pending_seek = NULL;
2868
2869   return TRUE;
2870
2871 fail:
2872   {
2873     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
2874     return FALSE;
2875   }
2876 out_of_memory:
2877   {
2878     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
2879         stream->n_samples);
2880     return FALSE;
2881   }
2882 index_too_big:
2883   {
2884     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
2885         "be larger than %uMB (broken file?)", stream->n_samples,
2886         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
2887     return FALSE;
2888   }
2889 }
2890
2891 /* find stream with @id */
2892 static inline QtDemuxStream *
2893 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
2894 {
2895   QtDemuxStream *stream;
2896   gint i;
2897
2898   /* check */
2899   if (G_UNLIKELY (!id)) {
2900     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
2901     return NULL;
2902   }
2903
2904   /* try to get it fast and simple */
2905   if (G_LIKELY (id <= qtdemux->n_streams)) {
2906     stream = qtdemux->streams[id - 1];
2907     if (G_LIKELY (stream->track_id == id))
2908       return stream;
2909   }
2910
2911   /* linear search otherwise */
2912   for (i = 0; i < qtdemux->n_streams; i++) {
2913     stream = qtdemux->streams[i];
2914     if (stream->track_id == id)
2915       return stream;
2916   }
2917   if (qtdemux->mss_mode) {
2918     /* mss should have only 1 stream anyway */
2919     return qtdemux->streams[0];
2920   }
2921
2922   return NULL;
2923 }
2924
2925 static gboolean
2926 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
2927     guint32 * fragment_number)
2928 {
2929   if (!gst_byte_reader_skip (mfhd, 4))
2930     goto fail;
2931   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
2932     goto fail;
2933   return TRUE;
2934 fail:
2935   {
2936     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
2937     return FALSE;
2938   }
2939 }
2940
2941 static gboolean
2942 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
2943     QtDemuxStream ** stream, guint32 * default_sample_duration,
2944     guint32 * default_sample_size, guint32 * default_sample_flags,
2945     gint64 * base_offset)
2946 {
2947   guint32 flags = 0;
2948   guint32 track_id = 0;
2949
2950   if (!gst_byte_reader_skip (tfhd, 1) ||
2951       !gst_byte_reader_get_uint24_be (tfhd, &flags))
2952     goto invalid_track;
2953
2954   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
2955     goto invalid_track;
2956
2957   *stream = qtdemux_find_stream (qtdemux, track_id);
2958   if (G_UNLIKELY (!*stream))
2959     goto unknown_stream;
2960
2961   if (flags & TF_DEFAULT_BASE_IS_MOOF)
2962     *base_offset = qtdemux->moof_offset;
2963
2964   if (flags & TF_BASE_DATA_OFFSET)
2965     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
2966       goto invalid_track;
2967
2968   /* obtain stream defaults */
2969   qtdemux_parse_trex (qtdemux, *stream,
2970       default_sample_duration, default_sample_size, default_sample_flags);
2971
2972   /* FIXME: Handle TF_SAMPLE_DESCRIPTION_INDEX properly */
2973   if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
2974     if (!gst_byte_reader_skip (tfhd, 4))
2975       goto invalid_track;
2976
2977   if (flags & TF_DEFAULT_SAMPLE_DURATION)
2978     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
2979       goto invalid_track;
2980
2981   if (flags & TF_DEFAULT_SAMPLE_SIZE)
2982     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
2983       goto invalid_track;
2984
2985   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
2986     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
2987       goto invalid_track;
2988
2989   return TRUE;
2990
2991 invalid_track:
2992   {
2993     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
2994     return FALSE;
2995   }
2996 unknown_stream:
2997   {
2998     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
2999     return TRUE;
3000   }
3001 }
3002
3003 static gboolean
3004 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3005     guint64 * decode_time)
3006 {
3007   guint32 version = 0;
3008
3009   if (!gst_byte_reader_get_uint32_be (br, &version))
3010     return FALSE;
3011
3012   version >>= 24;
3013   if (version == 1) {
3014     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3015       goto failed;
3016   } else {
3017     guint32 dec_time = 0;
3018     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3019       goto failed;
3020     *decode_time = dec_time;
3021   }
3022
3023   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3024       *decode_time);
3025
3026   return TRUE;
3027
3028 failed:
3029   {
3030     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3031     return FALSE;
3032   }
3033 }
3034
3035 /* Returns a pointer to a GstStructure containing the properties of
3036  * the stream sample identified by @sample_index. The caller must unref
3037  * the returned object after use. Returns NULL if unsuccessful. */
3038 static GstStructure *
3039 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3040     QtDemuxStream * stream, guint sample_index)
3041 {
3042   QtDemuxCencSampleSetInfo *info = NULL;
3043
3044   g_return_val_if_fail (stream != NULL, NULL);
3045   g_return_val_if_fail (stream->protected, NULL);
3046   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3047
3048   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3049
3050   /* Currently, cenc properties for groups of samples are not supported, so
3051    * simply return a copy of the default sample properties */
3052   return gst_structure_copy (info->default_properties);
3053 }
3054
3055 /* Parses the sizes of sample auxiliary information contained within a stream,
3056  * as given in a saiz box. Returns array of sample_count guint8 size values,
3057  * or NULL on failure */
3058 static guint8 *
3059 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3060     GstByteReader * br, guint32 * sample_count)
3061 {
3062   guint32 flags = 0;
3063   guint8 *info_sizes;
3064   guint8 default_info_size;
3065
3066   g_return_val_if_fail (qtdemux != NULL, NULL);
3067   g_return_val_if_fail (stream != NULL, NULL);
3068   g_return_val_if_fail (br != NULL, NULL);
3069   g_return_val_if_fail (sample_count != NULL, NULL);
3070
3071   if (!gst_byte_reader_get_uint32_be (br, &flags))
3072     return NULL;
3073
3074   if (flags & 0x1) {
3075     /* aux_info_type and aux_info_type_parameter are ignored */
3076     if (!gst_byte_reader_skip (br, 8))
3077       return NULL;
3078   }
3079
3080   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3081     return NULL;
3082   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3083
3084   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3085     return NULL;
3086   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3087
3088
3089   if (default_info_size == 0) {
3090     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3091       return NULL;
3092     }
3093   } else {
3094     info_sizes = g_new (guint8, *sample_count);
3095     memset (info_sizes, default_info_size, *sample_count);
3096   }
3097
3098   return info_sizes;
3099 }
3100
3101 /* Parses the offset of sample auxiliary information contained within a stream,
3102  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3103 static gboolean
3104 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3105     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3106     guint64 * offset)
3107 {
3108   guint8 version = 0;
3109   guint32 flags = 0;
3110   guint32 aux_info_type = 0;
3111   guint32 aux_info_type_parameter = 0;
3112   guint32 entry_count;
3113   guint32 off_32;
3114   guint64 off_64;
3115
3116   g_return_val_if_fail (qtdemux != NULL, FALSE);
3117   g_return_val_if_fail (stream != NULL, FALSE);
3118   g_return_val_if_fail (br != NULL, FALSE);
3119   g_return_val_if_fail (offset != NULL, FALSE);
3120
3121   if (!gst_byte_reader_get_uint8 (br, &version))
3122     return FALSE;
3123
3124   if (!gst_byte_reader_get_uint24_be (br, &flags))
3125     return FALSE;
3126
3127   if (flags & 0x1) {
3128     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type))
3129       return FALSE;
3130     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3131       return FALSE;
3132   } else if (stream->protected) {
3133     aux_info_type = stream->protection_scheme_type;
3134   } else {
3135     aux_info_type = stream->fourcc;
3136   }
3137
3138   if (info_type)
3139     *info_type = aux_info_type;
3140   if (info_type_parameter)
3141     *info_type_parameter = aux_info_type_parameter;
3142
3143   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3144       "aux_info_type_parameter:  %#06x",
3145       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3146
3147   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3148     return FALSE;
3149
3150   if (entry_count != 1) {
3151     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3152     return FALSE;
3153   }
3154
3155   if (version == 0) {
3156     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3157       return FALSE;
3158     *offset = (guint64) off_32;
3159   } else {
3160     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3161       return FALSE;
3162     *offset = off_64;
3163   }
3164
3165   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3166   return TRUE;
3167 }
3168
3169 static void
3170 qtdemux_gst_structure_free (GstStructure * gststructure)
3171 {
3172   if (gststructure) {
3173     gst_structure_free (gststructure);
3174   }
3175 }
3176
3177 /* Parses auxiliary information relating to samples protected using Common
3178  * Encryption (cenc); the format of this information is defined in
3179  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3180 static gboolean
3181 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3182     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3183 {
3184   QtDemuxCencSampleSetInfo *ss_info = NULL;
3185   guint8 size;
3186   gint i;
3187
3188   g_return_val_if_fail (qtdemux != NULL, FALSE);
3189   g_return_val_if_fail (stream != NULL, FALSE);
3190   g_return_val_if_fail (br != NULL, FALSE);
3191   g_return_val_if_fail (stream->protected, FALSE);
3192   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3193
3194   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3195
3196   if (ss_info->crypto_info) {
3197     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
3198     g_ptr_array_free (ss_info->crypto_info, TRUE);
3199   }
3200
3201   ss_info->crypto_info =
3202       g_ptr_array_new_full (sample_count,
3203       (GDestroyNotify) qtdemux_gst_structure_free);
3204
3205   for (i = 0; i < sample_count; ++i) {
3206     GstStructure *properties;
3207     guint16 n_subsamples;
3208     guint8 *data;
3209     guint iv_size;
3210     GstBuffer *buf;
3211
3212     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3213     if (properties == NULL) {
3214       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3215       return FALSE;
3216     }
3217     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3218       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3219       gst_structure_free (properties);
3220       return FALSE;
3221     }
3222     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3223       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3224       gst_structure_free (properties);
3225       return FALSE;
3226     }
3227     buf = gst_buffer_new_wrapped (data, iv_size);
3228     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3229     size = info_sizes[i];
3230     if (size > iv_size) {
3231       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3232           || !(n_subsamples > 0)) {
3233         gst_structure_free (properties);
3234         GST_ERROR_OBJECT (qtdemux,
3235             "failed to get subsample count for sample %u", i);
3236         return FALSE;
3237       }
3238       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3239       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3240         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3241             i);
3242         gst_structure_free (properties);
3243         return FALSE;
3244       }
3245       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3246       if (!buf) {
3247         gst_structure_free (properties);
3248         return FALSE;
3249       }
3250       gst_structure_set (properties,
3251           "subsample_count", G_TYPE_UINT, n_subsamples,
3252           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3253     } else {
3254       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3255     }
3256     g_ptr_array_add (ss_info->crypto_info, properties);
3257   }
3258   return TRUE;
3259 }
3260
3261 /* Converts a UUID in raw byte form to a string representation, as defined in
3262  * RFC 4122. The caller takes ownership of the returned string and is
3263  * responsible for freeing it after use. */
3264 static gchar *
3265 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3266 {
3267   const guint8 *uuid = (const guint8 *) uuid_bytes;
3268
3269   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3270       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3271       uuid[0], uuid[1], uuid[2], uuid[3],
3272       uuid[4], uuid[5], uuid[6], uuid[7],
3273       uuid[8], uuid[9], uuid[10], uuid[11],
3274       uuid[12], uuid[13], uuid[14], uuid[15]);
3275 }
3276
3277 /* Parses a Protection System Specific Header box (pssh), as defined in the
3278  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3279  * information needed by a specific content protection system in order to
3280  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3281  * otherwise. */
3282 static gboolean
3283 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3284 {
3285   gchar *sysid_string;
3286   guint32 pssh_size = QT_UINT32 (node->data);
3287   GstBuffer *pssh = NULL;
3288   GstEvent *event = NULL;
3289   guint32 parent_box_type;
3290   gint i;
3291
3292   if (G_UNLIKELY (pssh_size < 32U)) {
3293     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3294     return FALSE;
3295   }
3296
3297   sysid_string =
3298       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3299
3300   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3301
3302   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3303   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3304       gst_buffer_get_size (pssh));
3305
3306   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3307
3308   /* Push an event containing the pssh box onto the queues of all streams. */
3309   event = gst_event_new_protection (sysid_string, pssh,
3310       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3311   for (i = 0; i < qtdemux->n_streams; ++i) {
3312     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3313         gst_event_ref (event));
3314   }
3315   g_free (sysid_string);
3316   gst_event_unref (event);
3317   gst_buffer_unref (pssh);
3318   return TRUE;
3319 }
3320
3321 static gboolean
3322 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3323     guint64 moof_offset, QtDemuxStream * stream)
3324 {
3325   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3326   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3327   GNode *saiz_node, *saio_node, *pssh_node;
3328   GstByteReader saiz_data, saio_data;
3329   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3330   gint64 base_offset, running_offset;
3331   guint32 frag_num;
3332
3333   /* NOTE @stream ignored */
3334
3335   moof_node = g_node_new ((guint8 *) buffer);
3336   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3337   qtdemux_node_dump (qtdemux, moof_node);
3338
3339   /* Get fragment number from mfhd and check it's valid */
3340   mfhd_node =
3341       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3342   if (mfhd_node == NULL)
3343     goto missing_mfhd;
3344   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3345     goto fail;
3346   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3347
3348   /* unknown base_offset to start with */
3349   base_offset = running_offset = -1;
3350   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3351   while (traf_node) {
3352     guint64 decode_time = 0;
3353
3354     /* Fragment Header node */
3355     tfhd_node =
3356         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3357         &tfhd_data);
3358     if (!tfhd_node)
3359       goto missing_tfhd;
3360     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3361             &ds_size, &ds_flags, &base_offset))
3362       goto missing_tfhd;
3363
3364     /* The following code assumes at most a single set of sample auxiliary
3365      * data in the fragment (consisting of a saiz box and a corresponding saio
3366      * box); in theory, however, there could be multiple sets of sample
3367      * auxiliary data in a fragment. */
3368     saiz_node =
3369         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3370         &saiz_data);
3371     if (saiz_node) {
3372       guint8 *info_sizes;
3373       guint32 sample_count;
3374       guint32 info_type = 0;
3375       guint64 offset = 0;
3376       guint32 info_type_parameter = 0;
3377
3378       info_sizes = qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3379           &sample_count);
3380       if (G_UNLIKELY (info_sizes == NULL)) {
3381         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3382         goto fail;
3383       }
3384       saio_node =
3385           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3386           &saio_data);
3387       if (!saio_node) {
3388         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3389         goto fail;
3390       }
3391
3392       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3393                   &info_type, &info_type_parameter, &offset))) {
3394         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3395         g_free (info_sizes);
3396         goto fail;
3397       }
3398       if (base_offset > qtdemux->moof_offset)
3399         offset += (guint64) (base_offset - qtdemux->moof_offset);
3400       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3401         GstByteReader br;
3402         if (offset > length) {
3403           GST_ERROR_OBJECT (qtdemux, "cenc auxiliary info outside moof "
3404               "boxes is not supported");
3405           g_free (info_sizes);
3406           goto fail;
3407         }
3408         gst_byte_reader_init (&br, buffer + offset, length - offset);
3409         if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3410                 info_sizes, sample_count)) {
3411           GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3412           goto fail;
3413         }
3414       }
3415       g_free (info_sizes);
3416     }
3417
3418     tfdt_node =
3419         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3420         &tfdt_data);
3421     if (tfdt_node) {
3422       GstClockTime decode_time_ts;
3423
3424       /* We'll use decode_time to interpolate timestamps
3425        * in case the input timestamps are missing */
3426       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3427
3428       decode_time_ts = QTSTREAMTIME_TO_GSTTIME (stream, decode_time);
3429
3430       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3431           " (%" GST_TIME_FORMAT ")", decode_time,
3432           GST_TIME_ARGS (decode_time_ts));
3433
3434       /* Discard the fragment buffer timestamp info to avoid using it.
3435        * Rely on tfdt instead as it is more accurate than the timestamp
3436        * that is fetched from a manifest/playlist and is usually
3437        * less accurate. */
3438       qtdemux->fragment_start = -1;
3439     }
3440
3441     if (G_UNLIKELY (!stream)) {
3442       /* we lost track of offset, we'll need to regain it,
3443        * but can delay complaining until later or avoid doing so altogether */
3444       base_offset = -2;
3445       goto next;
3446     }
3447     if (G_UNLIKELY (base_offset < -1))
3448       goto lost_offset;
3449
3450     if (qtdemux->upstream_format_is_time)
3451       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3452
3453     /* Track Run node */
3454     trun_node =
3455         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3456         &trun_data);
3457     while (trun_node) {
3458       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3459           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3460           &running_offset, decode_time);
3461       /* iterate all siblings */
3462       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3463           &trun_data);
3464     }
3465     /* if no new base_offset provided for next traf,
3466      * base is end of current traf */
3467     base_offset = running_offset;
3468     running_offset = -1;
3469   next:
3470     /* iterate all siblings */
3471     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
3472   }
3473
3474   /* parse any protection system info */
3475   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
3476   while (pssh_node) {
3477     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
3478     qtdemux_parse_pssh (qtdemux, pssh_node);
3479     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
3480   }
3481
3482   g_node_destroy (moof_node);
3483   return TRUE;
3484
3485 missing_tfhd:
3486   {
3487     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
3488     goto fail;
3489   }
3490 missing_mfhd:
3491   {
3492     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
3493     goto fail;
3494   }
3495 lost_offset:
3496   {
3497     GST_DEBUG_OBJECT (qtdemux, "lost offset");
3498     goto fail;
3499   }
3500 fail:
3501   {
3502     g_node_destroy (moof_node);
3503     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3504         (_("This file is corrupt and cannot be played.")), (NULL));
3505     return FALSE;
3506   }
3507 }
3508
3509 #if 0
3510 /* might be used if some day we actually use mfra & co
3511  * for random access to fragments,
3512  * but that will require quite some modifications and much less relying
3513  * on a sample array */
3514 #endif
3515
3516 static gboolean
3517 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
3518 {
3519   QtDemuxStream *stream;
3520   guint32 ver_flags, track_id, len, num_entries, i;
3521   guint value_size, traf_size, trun_size, sample_size;
3522   guint64 time = 0, moof_offset = 0;
3523 #if 0
3524   GstBuffer *buf = NULL;
3525   GstFlowReturn ret;
3526 #endif
3527   GstByteReader tfra;
3528
3529   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
3530
3531   if (!gst_byte_reader_skip (&tfra, 8))
3532     return FALSE;
3533
3534   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
3535     return FALSE;
3536
3537   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
3538       || !gst_byte_reader_get_uint32_be (&tfra, &len)
3539       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
3540     return FALSE;
3541
3542   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
3543
3544   stream = qtdemux_find_stream (qtdemux, track_id);
3545   if (stream == NULL)
3546     goto unknown_trackid;
3547
3548   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
3549   sample_size = (len & 3) + 1;
3550   trun_size = ((len & 12) >> 2) + 1;
3551   traf_size = ((len & 48) >> 4) + 1;
3552
3553   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
3554       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
3555
3556   if (num_entries == 0)
3557     goto no_samples;
3558
3559   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
3560           value_size + value_size + traf_size + trun_size + sample_size))
3561     goto corrupt_file;
3562
3563   g_free (stream->ra_entries);
3564   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
3565   stream->n_ra_entries = num_entries;
3566
3567   for (i = 0; i < num_entries; i++) {
3568     qt_atom_parser_get_offset (&tfra, value_size, &time);
3569     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
3570     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
3571     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
3572     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
3573
3574     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
3575
3576     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
3577         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
3578
3579     stream->ra_entries[i].ts = time;
3580     stream->ra_entries[i].moof_offset = moof_offset;
3581
3582     /* don't want to go through the entire file and read all moofs at startup */
3583 #if 0
3584     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
3585     if (ret != GST_FLOW_OK)
3586       goto corrupt_file;
3587     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
3588         moof_offset, stream);
3589     gst_buffer_unref (buf);
3590 #endif
3591   }
3592
3593   check_update_duration (qtdemux, time);
3594
3595   return TRUE;
3596
3597 /* ERRORS */
3598 unknown_trackid:
3599   {
3600     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
3601     return FALSE;
3602   }
3603 corrupt_file:
3604   {
3605     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
3606     return FALSE;
3607   }
3608 no_samples:
3609   {
3610     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
3611     return FALSE;
3612   }
3613 }
3614
3615 static gboolean
3616 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
3617 {
3618   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
3619   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
3620   GstBuffer *mfro = NULL, *mfra = NULL;
3621   GstFlowReturn flow;
3622   gboolean ret = FALSE;
3623   GNode *mfra_node, *tfra_node;
3624   guint64 mfra_offset = 0;
3625   guint32 fourcc, mfra_size;
3626   gint64 len;
3627
3628   /* query upstream size in bytes */
3629   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
3630     goto size_query_failed;
3631
3632   /* mfro box should be at the very end of the file */
3633   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
3634   if (flow != GST_FLOW_OK)
3635     goto exit;
3636
3637   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
3638
3639   fourcc = QT_FOURCC (mfro_map.data + 4);
3640   if (fourcc != FOURCC_mfro)
3641     goto exit;
3642
3643   GST_INFO_OBJECT (qtdemux, "Found mfro box");
3644   if (mfro_map.size < 16)
3645     goto invalid_mfro_size;
3646
3647   mfra_size = QT_UINT32 (mfro_map.data + 12);
3648   if (mfra_size >= len)
3649     goto invalid_mfra_size;
3650
3651   mfra_offset = len - mfra_size;
3652
3653   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
3654       mfra_offset, mfra_size);
3655
3656   /* now get and parse mfra box */
3657   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
3658   if (flow != GST_FLOW_OK)
3659     goto broken_file;
3660
3661   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
3662
3663   mfra_node = g_node_new ((guint8 *) mfra_map.data);
3664   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
3665
3666   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
3667
3668   while (tfra_node) {
3669     qtdemux_parse_tfra (qtdemux, tfra_node);
3670     /* iterate all siblings */
3671     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
3672   }
3673   g_node_destroy (mfra_node);
3674
3675   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
3676   ret = TRUE;
3677
3678 exit:
3679
3680   if (mfro) {
3681     if (mfro_map.memory != NULL)
3682       gst_buffer_unmap (mfro, &mfro_map);
3683     gst_buffer_unref (mfro);
3684   }
3685   if (mfra) {
3686     if (mfra_map.memory != NULL)
3687       gst_buffer_unmap (mfra, &mfra_map);
3688     gst_buffer_unref (mfra);
3689   }
3690   return ret;
3691
3692 /* ERRORS */
3693 size_query_failed:
3694   {
3695     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
3696     goto exit;
3697   }
3698 invalid_mfro_size:
3699   {
3700     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
3701     goto exit;
3702   }
3703 invalid_mfra_size:
3704   {
3705     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
3706     goto exit;
3707   }
3708 broken_file:
3709   {
3710     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
3711     goto exit;
3712   }
3713 }
3714
3715 static guint64
3716 add_offset (guint64 offset, guint64 advance)
3717 {
3718   /* Avoid 64-bit overflow by clamping */
3719   if (offset > G_MAXUINT64 - advance)
3720     return G_MAXUINT64;
3721   return offset + advance;
3722 }
3723
3724 static GstFlowReturn
3725 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
3726 {
3727   guint64 length = 0;
3728   guint32 fourcc = 0;
3729   GstBuffer *buf = NULL;
3730   GstFlowReturn ret = GST_FLOW_OK;
3731   guint64 cur_offset = qtdemux->offset;
3732   GstMapInfo map;
3733
3734   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
3735   if (G_UNLIKELY (ret != GST_FLOW_OK))
3736     goto beach;
3737   gst_buffer_map (buf, &map, GST_MAP_READ);
3738   if (G_LIKELY (map.size >= 8))
3739     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
3740   gst_buffer_unmap (buf, &map);
3741   gst_buffer_unref (buf);
3742
3743   /* maybe we already got most we needed, so only consider this eof */
3744   if (G_UNLIKELY (length == 0)) {
3745     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
3746         (_("Invalid atom size.")),
3747         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
3748             GST_FOURCC_ARGS (fourcc)));
3749     ret = GST_FLOW_EOS;
3750     goto beach;
3751   }
3752
3753   switch (fourcc) {
3754     case FOURCC_moof:
3755       /* record for later parsing when needed */
3756       if (!qtdemux->moof_offset) {
3757         qtdemux->moof_offset = qtdemux->offset;
3758       }
3759       if (qtdemux_pull_mfro_mfra (qtdemux)) {
3760         /* FIXME */
3761       } else {
3762         qtdemux->offset += length;      /* skip moof and keep going */
3763       }
3764       if (qtdemux->got_moov) {
3765         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
3766         ret = GST_FLOW_EOS;
3767         goto beach;
3768       }
3769       break;
3770     case FOURCC_mdat:
3771     case FOURCC_free:
3772     case FOURCC_wide:
3773     case FOURCC_PICT:
3774     case FOURCC_pnot:
3775     {
3776       GST_LOG_OBJECT (qtdemux,
3777           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
3778           GST_FOURCC_ARGS (fourcc), cur_offset);
3779       qtdemux->offset = add_offset (qtdemux->offset, length);
3780       break;
3781     }
3782     case FOURCC_moov:
3783     {
3784       GstBuffer *moov = NULL;
3785
3786       if (qtdemux->got_moov) {
3787         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
3788         qtdemux->offset = add_offset (qtdemux->offset, length);
3789         goto beach;
3790       }
3791
3792       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
3793       if (ret != GST_FLOW_OK)
3794         goto beach;
3795       gst_buffer_map (moov, &map, GST_MAP_READ);
3796
3797       if (length != map.size) {
3798         /* Some files have a 'moov' atom at the end of the file which contains
3799          * a terminal 'free' atom where the body of the atom is missing.
3800          * Check for, and permit, this special case.
3801          */
3802         if (map.size >= 8) {
3803           guint8 *final_data = map.data + (map.size - 8);
3804           guint32 final_length = QT_UINT32 (final_data);
3805           guint32 final_fourcc = QT_FOURCC (final_data + 4);
3806
3807           if (final_fourcc == FOURCC_free
3808               && map.size + final_length - 8 == length) {
3809             /* Ok, we've found that special case. Allocate a new buffer with
3810              * that free atom actually present. */
3811             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
3812             gst_buffer_fill (newmoov, 0, map.data, map.size);
3813             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
3814             gst_buffer_unmap (moov, &map);
3815             gst_buffer_unref (moov);
3816             moov = newmoov;
3817             gst_buffer_map (moov, &map, GST_MAP_READ);
3818           }
3819         }
3820       }
3821
3822       if (length != map.size) {
3823         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
3824             (_("This file is incomplete and cannot be played.")),
3825             ("We got less than expected (received %" G_GSIZE_FORMAT
3826                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
3827                 (guint) length, cur_offset));
3828         gst_buffer_unmap (moov, &map);
3829         gst_buffer_unref (moov);
3830         ret = GST_FLOW_ERROR;
3831         goto beach;
3832       }
3833       qtdemux->offset += length;
3834
3835       qtdemux_parse_moov (qtdemux, map.data, length);
3836       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
3837
3838       qtdemux_parse_tree (qtdemux);
3839       g_node_destroy (qtdemux->moov_node);
3840       gst_buffer_unmap (moov, &map);
3841       gst_buffer_unref (moov);
3842       qtdemux->moov_node = NULL;
3843       qtdemux->got_moov = TRUE;
3844
3845       break;
3846     }
3847     case FOURCC_ftyp:
3848     {
3849       GstBuffer *ftyp = NULL;
3850
3851       /* extract major brand; might come in handy for ISO vs QT issues */
3852       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
3853       if (ret != GST_FLOW_OK)
3854         goto beach;
3855       qtdemux->offset += length;
3856       gst_buffer_map (ftyp, &map, GST_MAP_READ);
3857       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
3858       gst_buffer_unmap (ftyp, &map);
3859       gst_buffer_unref (ftyp);
3860       break;
3861     }
3862     case FOURCC_uuid:
3863     {
3864       GstBuffer *uuid = NULL;
3865
3866       /* uuid are extension atoms */
3867       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
3868       if (ret != GST_FLOW_OK)
3869         goto beach;
3870       qtdemux->offset += length;
3871       gst_buffer_map (uuid, &map, GST_MAP_READ);
3872       qtdemux_parse_uuid (qtdemux, map.data, map.size);
3873       gst_buffer_unmap (uuid, &map);
3874       gst_buffer_unref (uuid);
3875       break;
3876     }
3877     case FOURCC_sidx:
3878     {
3879       GstBuffer *sidx = NULL;
3880       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
3881       if (ret != GST_FLOW_OK)
3882         goto beach;
3883       qtdemux->offset += length;
3884       gst_buffer_map (sidx, &map, GST_MAP_READ);
3885       qtdemux_parse_sidx (qtdemux, map.data, map.size);
3886       gst_buffer_unmap (sidx, &map);
3887       gst_buffer_unref (sidx);
3888       break;
3889     }
3890     default:
3891     {
3892       GstBuffer *unknown = NULL;
3893
3894       GST_LOG_OBJECT (qtdemux,
3895           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
3896           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
3897           cur_offset);
3898       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
3899       if (ret != GST_FLOW_OK)
3900         goto beach;
3901       gst_buffer_map (unknown, &map, GST_MAP_READ);
3902       GST_MEMDUMP ("Unknown tag", map.data, map.size);
3903       gst_buffer_unmap (unknown, &map);
3904       gst_buffer_unref (unknown);
3905       qtdemux->offset += length;
3906       break;
3907     }
3908   }
3909
3910 beach:
3911   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
3912     /* digested all data, show what we have */
3913     qtdemux_prepare_streams (qtdemux);
3914     ret = qtdemux_expose_streams (qtdemux);
3915
3916     qtdemux->state = QTDEMUX_STATE_MOVIE;
3917     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
3918         qtdemux->state);
3919     return ret;
3920   }
3921   return ret;
3922 }
3923
3924 /* Seeks to the previous keyframe of the indexed stream and
3925  * aligns other streams with respect to the keyframe timestamp
3926  * of indexed stream. Only called in case of Reverse Playback
3927  */
3928 static GstFlowReturn
3929 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
3930 {
3931   guint8 n = 0;
3932   guint32 seg_idx = 0, k_index = 0;
3933   guint32 ref_seg_idx, ref_k_index;
3934   GstClockTime k_pos = 0, last_stop = 0;
3935   QtDemuxSegment *seg = NULL;
3936   QtDemuxStream *ref_str = NULL;
3937   guint64 seg_media_start_mov;  /* segment media start time in mov format */
3938   guint64 target_ts;
3939
3940   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
3941    * and finally align all the other streams on that timestamp with their
3942    * respective keyframes */
3943   for (n = 0; n < qtdemux->n_streams; n++) {
3944     QtDemuxStream *str = qtdemux->streams[n];
3945
3946     /* No candidate yet, take the first stream */
3947     if (!ref_str) {
3948       ref_str = str;
3949       continue;
3950     }
3951
3952     /* So that stream has a segment, we prefer video streams */
3953     if (str->subtype == FOURCC_vide) {
3954       ref_str = str;
3955       break;
3956     }
3957   }
3958
3959   if (G_UNLIKELY (!ref_str)) {
3960     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
3961     goto eos;
3962   }
3963
3964   if (G_UNLIKELY (!ref_str->from_sample)) {
3965     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
3966     goto eos;
3967   }
3968
3969   /* So that stream has been playing from from_sample to to_sample. We will
3970    * get the timestamp of the previous sample and search for a keyframe before
3971    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
3972   if (ref_str->subtype == FOURCC_vide) {
3973     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
3974         ref_str->from_sample - 1);
3975   } else {
3976     if (ref_str->from_sample >= 10)
3977       k_index = ref_str->from_sample - 10;
3978     else
3979       k_index = 0;
3980   }
3981
3982   target_ts =
3983       ref_str->samples[k_index].timestamp +
3984       ref_str->samples[k_index].pts_offset;
3985
3986   /* get current segment for that stream */
3987   seg = &ref_str->segments[ref_str->segment_index];
3988   /* Use segment start in original timescale for comparisons */
3989   seg_media_start_mov = seg->trak_media_start;
3990
3991   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
3992       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
3993       k_index, target_ts, seg_media_start_mov,
3994       GST_TIME_ARGS (seg->media_start));
3995
3996   /* Crawl back through segments to find the one containing this I frame */
3997   while (target_ts < seg_media_start_mov) {
3998     GST_DEBUG_OBJECT (qtdemux,
3999         "keyframe position (sample %u) is out of segment %u " " target %"
4000         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4001         ref_str->segment_index, target_ts, seg_media_start_mov);
4002
4003     if (G_UNLIKELY (!ref_str->segment_index)) {
4004       /* Reached first segment, let's consider it's EOS */
4005       goto eos;
4006     }
4007     ref_str->segment_index--;
4008     seg = &ref_str->segments[ref_str->segment_index];
4009     /* Use segment start in original timescale for comparisons */
4010     seg_media_start_mov = seg->trak_media_start;
4011   }
4012   /* Calculate time position of the keyframe and where we should stop */
4013   k_pos =
4014       QTSTREAMTIME_TO_GSTTIME (ref_str,
4015       target_ts - seg->trak_media_start) + seg->time;
4016   last_stop =
4017       QTSTREAMTIME_TO_GSTTIME (ref_str,
4018       ref_str->samples[ref_str->from_sample].timestamp -
4019       seg->trak_media_start) + seg->time;
4020
4021   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4022       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4023       k_index, GST_TIME_ARGS (k_pos));
4024
4025   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4026   qtdemux->segment.position = last_stop;
4027   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4028       GST_TIME_ARGS (last_stop));
4029
4030   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4031     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4032     goto eos;
4033   }
4034
4035   ref_seg_idx = ref_str->segment_index;
4036   ref_k_index = k_index;
4037
4038   /* Align them all on this */
4039   for (n = 0; n < qtdemux->n_streams; n++) {
4040     guint32 index = 0;
4041     GstClockTime seg_time = 0;
4042     QtDemuxStream *str = qtdemux->streams[n];
4043
4044     /* aligning reference stream again might lead to backing up to yet another
4045      * keyframe (due to timestamp rounding issues),
4046      * potentially putting more load on downstream; so let's try to avoid */
4047     if (str == ref_str) {
4048       seg_idx = ref_seg_idx;
4049       seg = &str->segments[seg_idx];
4050       k_index = ref_k_index;
4051       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4052           "sample at index %d", n, ref_str->segment_index, k_index);
4053     } else {
4054       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4055       GST_DEBUG_OBJECT (qtdemux,
4056           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4057           seg_idx, GST_TIME_ARGS (k_pos));
4058
4059       /* get segment and time in the segment */
4060       seg = &str->segments[seg_idx];
4061       seg_time = k_pos - seg->time;
4062
4063       /* get the media time in the segment.
4064        * No adjustment for empty "filler" segments */
4065       if (seg->media_start != GST_CLOCK_TIME_NONE)
4066         seg_time += seg->media_start;
4067
4068       /* get the index of the sample with media time */
4069       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4070       GST_DEBUG_OBJECT (qtdemux,
4071           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4072           GST_TIME_ARGS (seg_time), index);
4073
4074       /* find previous keyframe */
4075       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index);
4076     }
4077
4078     /* Remember until where we want to go */
4079     str->to_sample = str->from_sample - 1;
4080     /* Define our time position */
4081     target_ts =
4082         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4083     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4084     if (seg->media_start != GST_CLOCK_TIME_NONE)
4085       str->time_position -= seg->media_start;
4086
4087     /* Now seek back in time */
4088     gst_qtdemux_move_stream (qtdemux, str, k_index);
4089     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4090         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4091         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4092   }
4093
4094   return GST_FLOW_OK;
4095
4096 eos:
4097   return GST_FLOW_EOS;
4098 }
4099
4100 /* activate the given segment number @seg_idx of @stream at time @offset.
4101  * @offset is an absolute global position over all the segments.
4102  *
4103  * This will push out a NEWSEGMENT event with the right values and
4104  * position the stream index to the first decodable sample before
4105  * @offset.
4106  *
4107  * PULL-BASED
4108  */
4109 static gboolean
4110 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4111     guint32 seg_idx, GstClockTime offset)
4112 {
4113   GstEvent *event;
4114   QtDemuxSegment *segment;
4115   guint32 index, kf_index;
4116   GstClockTime seg_time;
4117   GstClockTime start, stop, time;
4118   gdouble rate;
4119
4120   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4121       seg_idx, GST_TIME_ARGS (offset));
4122
4123   /* update the current segment */
4124   stream->segment_index = seg_idx;
4125
4126   /* get the segment */
4127   segment = &stream->segments[seg_idx];
4128
4129   if (G_UNLIKELY (offset < segment->time)) {
4130     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4131         GST_TIME_ARGS (segment->time));
4132     return FALSE;
4133   }
4134
4135   /* segment lies beyond total indicated duration */
4136   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4137           segment->time > qtdemux->segment.duration)) {
4138     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4139         " < segment->time %" GST_TIME_FORMAT,
4140         GST_TIME_ARGS (qtdemux->segment.duration),
4141         GST_TIME_ARGS (segment->time));
4142     return FALSE;
4143   }
4144
4145   /* get time in this segment */
4146   seg_time = offset - segment->time;
4147
4148   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4149       GST_TIME_ARGS (seg_time));
4150
4151   if (G_UNLIKELY (seg_time > segment->duration)) {
4152     GST_LOG_OBJECT (stream->pad,
4153         "seg_time > segment->duration %" GST_TIME_FORMAT,
4154         GST_TIME_ARGS (segment->duration));
4155     seg_time = segment->duration;
4156   }
4157
4158   /* qtdemux->segment.stop is in outside-time-realm, whereas
4159    * segment->media_stop is in track-time-realm.
4160    *
4161    * In order to compare the two, we need to bring segment.stop
4162    * into the track-time-realm */
4163
4164   stop = qtdemux->segment.stop;
4165   if (stop == GST_CLOCK_TIME_NONE)
4166     stop = qtdemux->segment.duration;
4167   if (stop == GST_CLOCK_TIME_NONE)
4168     stop = segment->media_stop;
4169   else
4170     stop =
4171         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4172
4173   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4174     start = segment->time + seg_time;
4175     time = offset;
4176     stop = start - seg_time + segment->duration;
4177   } else if (qtdemux->segment.rate >= 0) {
4178     start = MIN (segment->media_start + seg_time, stop);
4179     time = offset;
4180   } else {
4181     if (segment->media_start >= qtdemux->segment.start) {
4182       time = segment->time;
4183     } else {
4184       time = segment->time + (qtdemux->segment.start - segment->media_start);
4185     }
4186
4187     start = MAX (segment->media_start, qtdemux->segment.start);
4188     stop = MIN (segment->media_start + seg_time, stop);
4189   }
4190
4191   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4192       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4193       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4194
4195   /* combine global rate with that of the segment */
4196   rate = segment->rate * qtdemux->segment.rate;
4197
4198   /* Copy flags from main segment */
4199   stream->segment.flags = qtdemux->segment.flags;
4200
4201   /* update the segment values used for clipping */
4202   stream->segment.offset = qtdemux->segment.offset;
4203   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4204   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4205   stream->segment.rate = rate;
4206   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4207       stream->cslg_shift);
4208   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4209       stream->cslg_shift);
4210   stream->segment.time = time;
4211   stream->segment.position = stream->segment.start;
4212
4213   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4214       &stream->segment);
4215
4216   /* now prepare and send the segment */
4217   if (stream->pad) {
4218     event = gst_event_new_segment (&stream->segment);
4219     if (stream->segment_seqnum) {
4220       gst_event_set_seqnum (event, stream->segment_seqnum);
4221     }
4222     gst_pad_push_event (stream->pad, event);
4223     /* assume we can send more data now */
4224     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4225     /* clear to send tags on this pad now */
4226     gst_qtdemux_push_tags (qtdemux, stream);
4227   }
4228
4229   /* in the fragmented case, we pick a fragment that starts before our
4230    * desired position and rely on downstream to wait for a keyframe
4231    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4232    * tfra entries tells us which trun/sample the key unit is in, but we don't
4233    * make use of this additional information at the moment) */
4234   if (qtdemux->fragmented) {
4235     stream->to_sample = G_MAXUINT32;
4236     return TRUE;
4237   }
4238
4239   /* and move to the keyframe before the indicated media time of the
4240    * segment */
4241   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4242     if (qtdemux->segment.rate >= 0) {
4243       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4244       stream->to_sample = G_MAXUINT32;
4245       GST_DEBUG_OBJECT (stream->pad,
4246           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4247           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4248           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4249     } else {
4250       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4251       stream->to_sample = index;
4252       GST_DEBUG_OBJECT (stream->pad,
4253           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4254           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4255           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4256     }
4257   } else {
4258     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4259         "this is an empty segment");
4260     return TRUE;
4261   }
4262
4263   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4264    * encountered an error and printed a message so we return appropriately */
4265   if (index == -1)
4266     return FALSE;
4267
4268   /* we're at the right spot */
4269   if (index == stream->sample_index) {
4270     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4271     return TRUE;
4272   }
4273
4274   /* find keyframe of the target index */
4275   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index);
4276
4277 /* *INDENT-OFF* */
4278 /* indent does stupid stuff with stream->samples[].timestamp */
4279
4280   /* if we move forwards, we don't have to go back to the previous
4281    * keyframe since we already sent that. We can also just jump to
4282    * the keyframe right before the target index if there is one. */
4283   if (index > stream->sample_index) {
4284     /* moving forwards check if we move past a keyframe */
4285     if (kf_index > stream->sample_index) {
4286       GST_DEBUG_OBJECT (stream->pad,
4287            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4288            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4289            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4290       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4291     } else {
4292       GST_DEBUG_OBJECT (stream->pad,
4293           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4294           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4295           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4296     }
4297   } else {
4298     GST_DEBUG_OBJECT (stream->pad,
4299         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4300         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4301         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4302     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4303   }
4304
4305 /* *INDENT-ON* */
4306
4307   return TRUE;
4308 }
4309
4310 /* prepare to get the current sample of @stream, getting essential values.
4311  *
4312  * This function will also prepare and send the segment when needed.
4313  *
4314  * Return FALSE if the stream is EOS.
4315  *
4316  * PULL-BASED
4317  */
4318 static gboolean
4319 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4320     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4321     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4322     gboolean * keyframe)
4323 {
4324   QtDemuxSample *sample;
4325   GstClockTime time_position;
4326   guint32 seg_idx;
4327
4328   g_return_val_if_fail (stream != NULL, FALSE);
4329
4330   time_position = stream->time_position;
4331   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4332     goto eos;
4333
4334   seg_idx = stream->segment_index;
4335   if (G_UNLIKELY (seg_idx == -1)) {
4336     /* find segment corresponding to time_position if we are looking
4337      * for a segment. */
4338     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4339   }
4340
4341   /* different segment, activate it, sample_index will be set. */
4342   if (G_UNLIKELY (stream->segment_index != seg_idx))
4343     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4344
4345   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4346                   segment_index]))) {
4347     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4348
4349     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4350         " prepare empty sample");
4351
4352     *empty = TRUE;
4353     *pts = *dts = time_position;
4354     *duration = seg->duration - (time_position - seg->time);
4355
4356     return TRUE;
4357   }
4358
4359   *empty = FALSE;
4360
4361   if (stream->sample_index == -1)
4362     stream->sample_index = 0;
4363
4364   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4365       stream->sample_index, stream->n_samples);
4366
4367   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4368     if (!qtdemux->fragmented)
4369       goto eos;
4370
4371     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4372     do {
4373       GstFlowReturn flow;
4374
4375       GST_OBJECT_LOCK (qtdemux);
4376       flow = qtdemux_add_fragmented_samples (qtdemux);
4377       GST_OBJECT_UNLOCK (qtdemux);
4378
4379       if (flow != GST_FLOW_OK)
4380         goto eos;
4381     }
4382     while (stream->sample_index >= stream->n_samples);
4383   }
4384
4385   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4386     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4387         stream->sample_index);
4388     return FALSE;
4389   }
4390
4391   /* now get the info for the sample we're at */
4392   sample = &stream->samples[stream->sample_index];
4393
4394   *dts = QTSAMPLE_DTS (stream, sample);
4395   *pts = QTSAMPLE_PTS (stream, sample);
4396   *offset = sample->offset;
4397   *size = sample->size;
4398   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4399   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4400
4401   return TRUE;
4402
4403   /* special cases */
4404 eos:
4405   {
4406     stream->time_position = GST_CLOCK_TIME_NONE;
4407     return FALSE;
4408   }
4409 }
4410
4411 /* move to the next sample in @stream.
4412  *
4413  * Moves to the next segment when needed.
4414  */
4415 static void
4416 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
4417 {
4418   QtDemuxSample *sample;
4419   QtDemuxSegment *segment;
4420
4421   /* get current segment */
4422   segment = &stream->segments[stream->segment_index];
4423
4424   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4425     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
4426     goto next_segment;
4427   }
4428
4429   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
4430     /* Mark the stream as EOS */
4431     GST_DEBUG_OBJECT (qtdemux,
4432         "reached max allowed sample %u, mark EOS", stream->to_sample);
4433     stream->time_position = GST_CLOCK_TIME_NONE;
4434     return;
4435   }
4436
4437   /* move to next sample */
4438   stream->sample_index++;
4439   stream->offset_in_sample = 0;
4440
4441   /* reached the last sample, we need the next segment */
4442   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
4443     goto next_segment;
4444
4445   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4446     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4447         stream->sample_index);
4448     return;
4449   }
4450
4451   /* get next sample */
4452   sample = &stream->samples[stream->sample_index];
4453
4454   /* see if we are past the segment */
4455   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
4456     goto next_segment;
4457
4458   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
4459     /* inside the segment, update time_position, looks very familiar to
4460      * GStreamer segments, doesn't it? */
4461     stream->time_position =
4462         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
4463   } else {
4464     /* not yet in segment, time does not yet increment. This means
4465      * that we are still prerolling keyframes to the decoder so it can
4466      * decode the first sample of the segment. */
4467     stream->time_position = segment->time;
4468   }
4469   return;
4470
4471   /* move to the next segment */
4472 next_segment:
4473   {
4474     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
4475
4476     if (stream->segment_index == stream->n_segments - 1) {
4477       /* are we at the end of the last segment, we're EOS */
4478       stream->time_position = GST_CLOCK_TIME_NONE;
4479     } else {
4480       /* else we're only at the end of the current segment */
4481       stream->time_position = segment->stop_time;
4482     }
4483     /* make sure we select a new segment */
4484
4485     /* accumulate previous segments */
4486     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
4487       stream->accumulated_base +=
4488           (stream->segment.stop -
4489           stream->segment.start) / ABS (stream->segment.rate);
4490
4491     stream->segment_index = -1;
4492   }
4493 }
4494
4495 static void
4496 gst_qtdemux_sync_streams (GstQTDemux * demux)
4497 {
4498   gint i;
4499
4500   if (demux->n_streams <= 1)
4501     return;
4502
4503   for (i = 0; i < demux->n_streams; i++) {
4504     QtDemuxStream *stream;
4505     GstClockTime end_time;
4506
4507     stream = demux->streams[i];
4508
4509     if (!stream->pad)
4510       continue;
4511
4512     /* TODO advance time on subtitle streams here, if any some day */
4513
4514     /* some clips/trailers may have unbalanced streams at the end,
4515      * so send EOS on shorter stream to prevent stalling others */
4516
4517     /* do not mess with EOS if SEGMENT seeking */
4518     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
4519       continue;
4520
4521     if (demux->pullbased) {
4522       /* loop mode is sample time based */
4523       if (!STREAM_IS_EOS (stream))
4524         continue;
4525     } else {
4526       /* push mode is byte position based */
4527       if (stream->n_samples &&
4528           stream->samples[stream->n_samples - 1].offset >= demux->offset)
4529         continue;
4530     }
4531
4532     if (stream->sent_eos)
4533       continue;
4534
4535     /* only act if some gap */
4536     end_time = stream->segments[stream->n_segments - 1].stop_time;
4537     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
4538         ", stream end: %" GST_TIME_FORMAT,
4539         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
4540     if (GST_CLOCK_TIME_IS_VALID (end_time)
4541         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
4542       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
4543           GST_PAD_NAME (stream->pad));
4544       stream->sent_eos = TRUE;
4545       gst_pad_push_event (stream->pad, gst_event_new_eos ());
4546     }
4547   }
4548 }
4549
4550 /* EOS and NOT_LINKED need to be combined. This means that we return:
4551  *
4552  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
4553  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
4554  */
4555 static GstFlowReturn
4556 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
4557     GstFlowReturn ret)
4558 {
4559   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
4560
4561   if (stream->pad)
4562     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
4563         ret);
4564   else
4565     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
4566
4567   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
4568   return ret;
4569 }
4570
4571 /* the input buffer metadata must be writable. Returns NULL when the buffer is
4572  * completely clipped
4573  *
4574  * Should be used only with raw buffers */
4575 static GstBuffer *
4576 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4577     GstBuffer * buf)
4578 {
4579   guint64 start, stop, cstart, cstop, diff;
4580   GstClockTime pts, duration;
4581   gsize size, osize;
4582   gint num_rate, denom_rate;
4583   gint frame_size;
4584   gboolean clip_data;
4585   guint offset;
4586
4587   osize = size = gst_buffer_get_size (buf);
4588   offset = 0;
4589
4590   /* depending on the type, setup the clip parameters */
4591   if (stream->subtype == FOURCC_soun) {
4592     frame_size = stream->bytes_per_frame;
4593     num_rate = GST_SECOND;
4594     denom_rate = (gint) stream->rate;
4595     clip_data = TRUE;
4596   } else if (stream->subtype == FOURCC_vide) {
4597     frame_size = size;
4598     num_rate = stream->fps_n;
4599     denom_rate = stream->fps_d;
4600     clip_data = FALSE;
4601   } else
4602     goto wrong_type;
4603
4604   if (frame_size <= 0)
4605     goto bad_frame_size;
4606
4607   /* we can only clip if we have a valid pts */
4608   pts = GST_BUFFER_PTS (buf);
4609   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
4610     goto no_pts;
4611
4612   duration = GST_BUFFER_DURATION (buf);
4613
4614   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
4615     duration =
4616         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
4617   }
4618
4619   start = pts;
4620   stop = start + duration;
4621
4622   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
4623               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
4624     goto clipped;
4625
4626   /* see if some clipping happened */
4627   diff = cstart - start;
4628   if (diff > 0) {
4629     pts += diff;
4630     duration -= diff;
4631
4632     if (clip_data) {
4633       /* bring clipped time to samples and to bytes */
4634       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4635       diff *= frame_size;
4636
4637       GST_DEBUG_OBJECT (qtdemux,
4638           "clipping start to %" GST_TIME_FORMAT " %"
4639           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
4640
4641       offset = diff;
4642       size -= diff;
4643     }
4644   }
4645   diff = stop - cstop;
4646   if (diff > 0) {
4647     duration -= diff;
4648
4649     if (clip_data) {
4650       /* bring clipped time to samples and then to bytes */
4651       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
4652       diff *= frame_size;
4653       GST_DEBUG_OBJECT (qtdemux,
4654           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
4655           " bytes", GST_TIME_ARGS (cstop), diff);
4656       size -= diff;
4657     }
4658   }
4659
4660   if (offset != 0 || size != osize)
4661     gst_buffer_resize (buf, offset, size);
4662
4663   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
4664   GST_BUFFER_PTS (buf) = pts;
4665   GST_BUFFER_DURATION (buf) = duration;
4666
4667   return buf;
4668
4669   /* dropped buffer */
4670 wrong_type:
4671   {
4672     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
4673     return buf;
4674   }
4675 bad_frame_size:
4676   {
4677     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
4678     return buf;
4679   }
4680 no_pts:
4681   {
4682     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
4683     return buf;
4684   }
4685 clipped:
4686   {
4687     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
4688     gst_buffer_unref (buf);
4689     return NULL;
4690   }
4691 }
4692
4693 /* the input buffer metadata must be writable,
4694  * but time/duration etc not yet set and need not be preserved */
4695 static GstBuffer *
4696 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
4697     GstBuffer * buf)
4698 {
4699   GstMapInfo map;
4700   guint nsize = 0;
4701   gchar *str;
4702
4703   /* not many cases for now */
4704   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
4705     /* send a one time dvd clut event */
4706     if (stream->pending_event && stream->pad)
4707       gst_pad_push_event (stream->pad, stream->pending_event);
4708     stream->pending_event = NULL;
4709   }
4710
4711   if (G_UNLIKELY (stream->subtype != FOURCC_text
4712           && stream->subtype != FOURCC_sbtl &&
4713           stream->subtype != FOURCC_subp)) {
4714     return buf;
4715   }
4716
4717   gst_buffer_map (buf, &map, GST_MAP_READ);
4718
4719   /* empty buffer is sent to terminate previous subtitle */
4720   if (map.size <= 2) {
4721     gst_buffer_unmap (buf, &map);
4722     gst_buffer_unref (buf);
4723     return NULL;
4724   }
4725   if (stream->subtype == FOURCC_subp) {
4726     /* That's all the processing needed for subpictures */
4727     gst_buffer_unmap (buf, &map);
4728     return buf;
4729   }
4730
4731   nsize = GST_READ_UINT16_BE (map.data);
4732   nsize = MIN (nsize, map.size - 2);
4733
4734   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
4735       nsize, map.size);
4736
4737   /* takes care of UTF-8 validation or UTF-16 recognition,
4738    * no other encoding expected */
4739   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
4740   gst_buffer_unmap (buf, &map);
4741   if (str) {
4742     gst_buffer_unref (buf);
4743     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
4744   } else {
4745     /* this should not really happen unless the subtitle is corrupted */
4746     gst_buffer_unref (buf);
4747     buf = NULL;
4748   }
4749
4750   /* FIXME ? convert optional subsequent style info to markup */
4751
4752   return buf;
4753 }
4754
4755 /* Sets a buffer's attributes properly and pushes it downstream.
4756  * Also checks for additional actions and custom processing that may
4757  * need to be done first.
4758  */
4759 static GstFlowReturn
4760 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
4761     QtDemuxStream * stream, GstBuffer * buf,
4762     GstClockTime dts, GstClockTime pts, GstClockTime duration,
4763     gboolean keyframe, GstClockTime position, guint64 byte_position)
4764 {
4765   GstFlowReturn ret = GST_FLOW_OK;
4766
4767   /* offset the timestamps according to the edit list */
4768
4769   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
4770     gchar *url;
4771     GstMapInfo map;
4772
4773     gst_buffer_map (buf, &map, GST_MAP_READ);
4774     url = g_strndup ((gchar *) map.data, map.size);
4775     gst_buffer_unmap (buf, &map);
4776     if (url != NULL && strlen (url) != 0) {
4777       /* we have RTSP redirect now */
4778       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
4779           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
4780               gst_structure_new ("redirect",
4781                   "new-location", G_TYPE_STRING, url, NULL)));
4782       qtdemux->posted_redirect = TRUE;
4783     } else {
4784       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
4785           "posting");
4786     }
4787     g_free (url);
4788   }
4789
4790   /* position reporting */
4791   if (qtdemux->segment.rate >= 0) {
4792     qtdemux->segment.position = position;
4793     gst_qtdemux_sync_streams (qtdemux);
4794   }
4795
4796   if (G_UNLIKELY (!stream->pad)) {
4797     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
4798     gst_buffer_unref (buf);
4799     goto exit;
4800   }
4801
4802   /* send out pending buffers */
4803   while (stream->buffers) {
4804     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
4805
4806     if (G_UNLIKELY (stream->discont)) {
4807       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4808       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
4809       stream->discont = FALSE;
4810     } else {
4811       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4812     }
4813
4814     gst_pad_push (stream->pad, buffer);
4815
4816     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
4817   }
4818
4819   /* we're going to modify the metadata */
4820   buf = gst_buffer_make_writable (buf);
4821
4822   if (G_UNLIKELY (stream->need_process))
4823     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
4824
4825   if (!buf) {
4826     goto exit;
4827   }
4828
4829   GST_BUFFER_DTS (buf) = dts;
4830   GST_BUFFER_PTS (buf) = pts;
4831   GST_BUFFER_DURATION (buf) = duration;
4832   GST_BUFFER_OFFSET (buf) = -1;
4833   GST_BUFFER_OFFSET_END (buf) = -1;
4834
4835   if (G_UNLIKELY (stream->rgb8_palette))
4836     gst_buffer_append_memory (buf, gst_memory_ref (stream->rgb8_palette));
4837
4838   if (G_UNLIKELY (stream->padding)) {
4839     gst_buffer_resize (buf, stream->padding, -1);
4840   }
4841 #if 0
4842   if (G_UNLIKELY (qtdemux->element_index)) {
4843     GstClockTime stream_time;
4844
4845     stream_time =
4846         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
4847         timestamp);
4848     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
4849       GST_LOG_OBJECT (qtdemux,
4850           "adding association %" GST_TIME_FORMAT "-> %"
4851           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
4852       gst_index_add_association (qtdemux->element_index,
4853           qtdemux->index_id,
4854           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
4855           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
4856           GST_FORMAT_BYTES, byte_position, NULL);
4857     }
4858   }
4859 #endif
4860
4861   if (stream->need_clip)
4862     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
4863
4864   if (G_UNLIKELY (buf == NULL))
4865     goto exit;
4866
4867   if (G_UNLIKELY (stream->discont)) {
4868     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
4869     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
4870     stream->discont = FALSE;
4871   } else {
4872     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
4873   }
4874
4875   if (!keyframe) {
4876     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
4877     stream->on_keyframe = FALSE;
4878   } else {
4879     stream->on_keyframe = TRUE;
4880   }
4881
4882
4883   GST_LOG_OBJECT (qtdemux,
4884       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
4885       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
4886       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
4887       GST_PAD_NAME (stream->pad));
4888
4889   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
4890     GstStructure *crypto_info;
4891     QtDemuxCencSampleSetInfo *info =
4892         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
4893     gint index;
4894     GstEvent *event;
4895
4896     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
4897       gst_pad_push_event (stream->pad, event);
4898     }
4899
4900     index = stream->sample_index - (stream->n_samples - info->crypto_info->len);
4901     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
4902       /* steal structure from array */
4903       crypto_info = g_ptr_array_index (info->crypto_info, index);
4904       g_ptr_array_index (info->crypto_info, index) = NULL;
4905       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u]", index);
4906       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
4907         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
4908     }
4909   }
4910
4911   ret = gst_pad_push (stream->pad, buf);
4912
4913   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
4914     /* mark position in stream, we'll need this to know when to send GAP event */
4915     stream->segment.position = pts + duration;
4916   }
4917
4918 exit:
4919   return ret;
4920 }
4921
4922 static const QtDemuxRandomAccessEntry *
4923 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4924     GstClockTime pos, gboolean after)
4925 {
4926   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
4927   guint n_entries = stream->n_ra_entries;
4928   guint i;
4929
4930   /* we assume the table is sorted */
4931   for (i = 0; i < n_entries; ++i) {
4932     if (entries[i].ts > pos)
4933       break;
4934   }
4935
4936   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
4937    * probably okay to assume that the index lists the very first fragment */
4938   if (i == 0)
4939     return &entries[0];
4940
4941   if (after)
4942     return &entries[i];
4943   else
4944     return &entries[i - 1];
4945 }
4946
4947 static gboolean
4948 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
4949 {
4950   const QtDemuxRandomAccessEntry *best_entry = NULL;
4951   guint i;
4952
4953   GST_OBJECT_LOCK (qtdemux);
4954
4955   g_assert (qtdemux->n_streams > 0);
4956
4957   for (i = 0; i < qtdemux->n_streams; i++) {
4958     const QtDemuxRandomAccessEntry *entry;
4959     QtDemuxStream *stream;
4960     gboolean is_audio_or_video;
4961
4962     stream = qtdemux->streams[i];
4963
4964     g_free (stream->samples);
4965     stream->samples = NULL;
4966     stream->n_samples = 0;
4967     stream->stbl_index = -1;    /* no samples have yet been parsed */
4968     stream->sample_index = -1;
4969
4970     if (stream->ra_entries == NULL)
4971       continue;
4972
4973     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
4974       is_audio_or_video = TRUE;
4975     else
4976       is_audio_or_video = FALSE;
4977
4978     entry =
4979         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
4980         stream->time_position, !is_audio_or_video);
4981
4982     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
4983         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
4984
4985     stream->pending_seek = entry;
4986
4987     /* decide position to jump to just based on audio/video tracks, not subs */
4988     if (!is_audio_or_video)
4989       continue;
4990
4991     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
4992       best_entry = entry;
4993   }
4994
4995   if (best_entry == NULL) {
4996     GST_OBJECT_UNLOCK (qtdemux);
4997     return FALSE;
4998   }
4999
5000   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5001       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5002       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5003       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5004
5005   qtdemux->moof_offset = best_entry->moof_offset;
5006
5007   qtdemux_add_fragmented_samples (qtdemux);
5008
5009   GST_OBJECT_UNLOCK (qtdemux);
5010   return TRUE;
5011 }
5012
5013 static GstFlowReturn
5014 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5015 {
5016   GstFlowReturn ret = GST_FLOW_OK;
5017   GstBuffer *buf = NULL;
5018   QtDemuxStream *stream;
5019   GstClockTime min_time;
5020   guint64 offset = 0;
5021   GstClockTime dts = GST_CLOCK_TIME_NONE;
5022   GstClockTime pts = GST_CLOCK_TIME_NONE;
5023   GstClockTime duration = 0;
5024   gboolean keyframe = FALSE;
5025   guint sample_size = 0;
5026   gboolean empty = 0;
5027   guint size;
5028   gint index;
5029   gint i;
5030
5031   gst_qtdemux_push_pending_newsegment (qtdemux);
5032
5033   if (qtdemux->fragmented_seek_pending) {
5034     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5035     gst_qtdemux_do_fragmented_seek (qtdemux);
5036     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5037     qtdemux->fragmented_seek_pending = FALSE;
5038   }
5039
5040   /* Figure out the next stream sample to output, min_time is expressed in
5041    * global time and runs over the edit list segments. */
5042   min_time = G_MAXUINT64;
5043   index = -1;
5044   for (i = 0; i < qtdemux->n_streams; i++) {
5045     GstClockTime position;
5046
5047     stream = qtdemux->streams[i];
5048     position = stream->time_position;
5049
5050     /* position of -1 is EOS */
5051     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5052       min_time = position;
5053       index = i;
5054     }
5055   }
5056   /* all are EOS */
5057   if (G_UNLIKELY (index == -1)) {
5058     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5059     goto eos;
5060   }
5061
5062   /* check for segment end */
5063   if (G_UNLIKELY (qtdemux->segment.stop != -1
5064           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5065               || (qtdemux->segment.rate < 0
5066                   && qtdemux->segment.start > min_time))
5067           && qtdemux->streams[index]->on_keyframe)) {
5068     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5069     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5070     goto eos_stream;
5071   }
5072
5073   /* gap events for subtitle streams */
5074   for (i = 0; i < qtdemux->n_streams; i++) {
5075     stream = qtdemux->streams[i];
5076     if (stream->pad && (stream->subtype == FOURCC_subp
5077             || stream->subtype == FOURCC_text
5078             || stream->subtype == FOURCC_sbtl)) {
5079       /* send one second gap events until the stream catches up */
5080       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5081       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5082           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5083           stream->segment.position + GST_SECOND < min_time) {
5084         GstEvent *gap =
5085             gst_event_new_gap (stream->segment.position, GST_SECOND);
5086         gst_pad_push_event (stream->pad, gap);
5087         stream->segment.position += GST_SECOND;
5088       }
5089     }
5090   }
5091
5092   stream = qtdemux->streams[index];
5093   if (stream->new_caps) {
5094     gst_qtdemux_configure_stream (qtdemux, stream);
5095     qtdemux_do_allocation (qtdemux, stream);
5096   }
5097
5098   /* fetch info for the current sample of this stream */
5099   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5100               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5101     goto eos_stream;
5102
5103   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5104   if (G_UNLIKELY (qtdemux->
5105           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5106     if (stream->subtype == FOURCC_vide && !keyframe) {
5107       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5108       goto next;
5109     }
5110   }
5111
5112   GST_DEBUG_OBJECT (qtdemux,
5113       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5114       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5115       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5116       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5117
5118   if (G_UNLIKELY (empty)) {
5119     /* empty segment, push a gap and move to the next one */
5120     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5121     stream->segment.position = pts + duration;
5122     goto next;
5123   }
5124
5125   /* hmm, empty sample, skip and move to next sample */
5126   if (G_UNLIKELY (sample_size <= 0))
5127     goto next;
5128
5129   /* last pushed sample was out of boundary, goto next sample */
5130   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5131     goto next;
5132
5133   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5134     size = sample_size;
5135   } else {
5136     GST_DEBUG_OBJECT (qtdemux,
5137         "size %d larger than stream max_buffer_size %d, trimming",
5138         sample_size, stream->max_buffer_size);
5139     size =
5140         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5141   }
5142
5143   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5144       offset);
5145
5146   if (stream->use_allocator) {
5147     /* if we have a per-stream allocator, use it */
5148     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5149   }
5150
5151   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5152       size, &buf);
5153   if (G_UNLIKELY (ret != GST_FLOW_OK))
5154     goto beach;
5155
5156   if (size != sample_size) {
5157     pts += gst_util_uint64_scale_int (GST_SECOND,
5158         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5159     dts += gst_util_uint64_scale_int (GST_SECOND,
5160         stream->offset_in_sample / stream->bytes_per_frame, stream->timescale);
5161     duration = gst_util_uint64_scale_int (GST_SECOND,
5162         size / stream->bytes_per_frame, stream->timescale);
5163   }
5164
5165   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5166       dts, pts, duration, keyframe, min_time, offset);
5167
5168   if (size != sample_size) {
5169     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5170     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5171
5172     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5173         sample->timestamp + stream->offset_in_sample / stream->bytes_per_frame);
5174     if (time_position >= segment->media_start) {
5175       /* inside the segment, update time_position, looks very familiar to
5176        * GStreamer segments, doesn't it? */
5177       stream->time_position = (time_position - segment->media_start) +
5178           segment->time;
5179     } else {
5180       /* not yet in segment, time does not yet increment. This means
5181        * that we are still prerolling keyframes to the decoder so it can
5182        * decode the first sample of the segment. */
5183       stream->time_position = segment->time;
5184     }
5185   }
5186
5187   /* combine flows */
5188   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5189   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5190    * we have no more data for the pad to push */
5191   if (ret == GST_FLOW_EOS)
5192     ret = GST_FLOW_OK;
5193
5194   stream->offset_in_sample += size;
5195   if (stream->offset_in_sample >= sample_size) {
5196     gst_qtdemux_advance_sample (qtdemux, stream);
5197   }
5198   goto beach;
5199
5200 next:
5201   gst_qtdemux_advance_sample (qtdemux, stream);
5202
5203 beach:
5204   return ret;
5205
5206   /* special cases */
5207 eos:
5208   {
5209     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5210     ret = GST_FLOW_EOS;
5211     goto beach;
5212   }
5213 eos_stream:
5214   {
5215     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5216     /* EOS will be raised if all are EOS */
5217     ret = GST_FLOW_OK;
5218     goto beach;
5219   }
5220 }
5221
5222 static void
5223 gst_qtdemux_loop (GstPad * pad)
5224 {
5225   GstQTDemux *qtdemux;
5226   guint64 cur_offset;
5227   GstFlowReturn ret;
5228
5229   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5230
5231   cur_offset = qtdemux->offset;
5232   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
5233       cur_offset, qtdemux->state);
5234
5235   switch (qtdemux->state) {
5236     case QTDEMUX_STATE_INITIAL:
5237     case QTDEMUX_STATE_HEADER:
5238       ret = gst_qtdemux_loop_state_header (qtdemux);
5239       break;
5240     case QTDEMUX_STATE_MOVIE:
5241       ret = gst_qtdemux_loop_state_movie (qtdemux);
5242       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5243         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5244       }
5245       break;
5246     default:
5247       /* ouch */
5248       goto invalid_state;
5249   }
5250
5251   /* if something went wrong, pause */
5252   if (ret != GST_FLOW_OK)
5253     goto pause;
5254
5255 done:
5256   gst_object_unref (qtdemux);
5257   return;
5258
5259   /* ERRORS */
5260 invalid_state:
5261   {
5262     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5263         (NULL), ("streaming stopped, invalid state"));
5264     gst_pad_pause_task (pad);
5265     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5266     goto done;
5267   }
5268 pause:
5269   {
5270     const gchar *reason = gst_flow_get_name (ret);
5271
5272     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5273
5274     gst_pad_pause_task (pad);
5275
5276     /* fatal errors need special actions */
5277     /* check EOS */
5278     if (ret == GST_FLOW_EOS) {
5279       if (qtdemux->n_streams == 0) {
5280         /* we have no streams, post an error */
5281         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5282       }
5283       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5284         gint64 stop;
5285
5286         if ((stop = qtdemux->segment.stop) == -1)
5287           stop = qtdemux->segment.duration;
5288
5289         if (qtdemux->segment.rate >= 0) {
5290           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5291           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5292               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5293                   GST_FORMAT_TIME, stop));
5294           gst_qtdemux_push_event (qtdemux,
5295               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
5296         } else {
5297           /*  For Reverse Playback */
5298           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
5299           gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5300               gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5301                   GST_FORMAT_TIME, qtdemux->segment.start));
5302           gst_qtdemux_push_event (qtdemux,
5303               gst_event_new_segment_done (GST_FORMAT_TIME,
5304                   qtdemux->segment.start));
5305         }
5306       } else {
5307         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
5308         gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5309       }
5310     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
5311       GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5312           (NULL), ("streaming stopped, reason %s", reason));
5313       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5314     }
5315     goto done;
5316   }
5317 }
5318
5319 /*
5320  * has_next_entry
5321  *
5322  * Returns if there are samples to be played.
5323  */
5324 static gboolean
5325 has_next_entry (GstQTDemux * demux)
5326 {
5327   QtDemuxStream *stream;
5328   int i;
5329
5330   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
5331
5332   for (i = 0; i < demux->n_streams; i++) {
5333     stream = demux->streams[i];
5334
5335     if (stream->sample_index == -1) {
5336       stream->sample_index = 0;
5337       stream->offset_in_sample = 0;
5338     }
5339
5340     if (stream->sample_index >= stream->n_samples) {
5341       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5342       continue;
5343     }
5344     GST_DEBUG_OBJECT (demux, "Found a sample");
5345     return TRUE;
5346   }
5347
5348   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
5349   return FALSE;
5350 }
5351
5352 /*
5353  * next_entry_size
5354  *
5355  * Returns the size of the first entry at the current offset.
5356  * If -1, there are none (which means EOS or empty file).
5357  */
5358 static guint64
5359 next_entry_size (GstQTDemux * demux)
5360 {
5361   QtDemuxStream *stream;
5362   int i;
5363   int smallidx = -1;
5364   guint64 smalloffs = (guint64) - 1;
5365   QtDemuxSample *sample;
5366
5367   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
5368       demux->offset);
5369
5370   for (i = 0; i < demux->n_streams; i++) {
5371     stream = demux->streams[i];
5372
5373     if (stream->sample_index == -1) {
5374       stream->sample_index = 0;
5375       stream->offset_in_sample = 0;
5376     }
5377
5378     if (stream->sample_index >= stream->n_samples) {
5379       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
5380       continue;
5381     }
5382
5383     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
5384       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
5385           stream->sample_index);
5386       return -1;
5387     }
5388
5389     sample = &stream->samples[stream->sample_index];
5390
5391     GST_LOG_OBJECT (demux,
5392         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5393         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
5394         sample->offset, sample->size);
5395
5396     if (((smalloffs == -1)
5397             || (sample->offset < smalloffs)) && (sample->size)) {
5398       smallidx = i;
5399       smalloffs = sample->offset;
5400     }
5401   }
5402
5403   GST_LOG_OBJECT (demux,
5404       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
5405       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
5406
5407   if (smallidx == -1)
5408     return -1;
5409
5410   stream = demux->streams[smallidx];
5411   sample = &stream->samples[stream->sample_index];
5412
5413   if (sample->offset >= demux->offset) {
5414     demux->todrop = sample->offset - demux->offset;
5415     return sample->size + demux->todrop;
5416   }
5417
5418   GST_DEBUG_OBJECT (demux,
5419       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
5420   return -1;
5421 }
5422
5423 static void
5424 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
5425 {
5426   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
5427
5428   gst_element_post_message (GST_ELEMENT_CAST (demux),
5429       gst_message_new_element (GST_OBJECT_CAST (demux),
5430           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
5431 }
5432
5433 static gboolean
5434 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
5435 {
5436   GstEvent *event;
5437   gboolean res = 0;
5438
5439   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
5440
5441   event =
5442       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
5443       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
5444       GST_SEEK_TYPE_NONE, -1);
5445
5446   res = gst_pad_push_event (demux->sinkpad, event);
5447
5448   return res;
5449 }
5450
5451 /* check for seekable upstream, above and beyond a mere query */
5452 static void
5453 gst_qtdemux_check_seekability (GstQTDemux * demux)
5454 {
5455   GstQuery *query;
5456   gboolean seekable = FALSE;
5457   gint64 start = -1, stop = -1;
5458
5459   if (demux->upstream_size)
5460     return;
5461
5462   query = gst_query_new_seeking (GST_FORMAT_BYTES);
5463   if (!gst_pad_peer_query (demux->sinkpad, query)) {
5464     GST_DEBUG_OBJECT (demux, "seeking query failed");
5465     goto done;
5466   }
5467
5468   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
5469
5470   /* try harder to query upstream size if we didn't get it the first time */
5471   if (seekable && stop == -1) {
5472     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
5473     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
5474   }
5475
5476   /* if upstream doesn't know the size, it's likely that it's not seekable in
5477    * practice even if it technically may be seekable */
5478   if (seekable && (start != 0 || stop <= start)) {
5479     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
5480     seekable = FALSE;
5481   }
5482
5483 done:
5484   gst_query_unref (query);
5485
5486   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
5487       G_GUINT64_FORMAT ")", seekable, start, stop);
5488   demux->upstream_seekable = seekable;
5489   demux->upstream_size = seekable ? stop : -1;
5490 }
5491
5492 static void
5493 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
5494 {
5495   g_return_if_fail (bytes <= demux->todrop);
5496
5497   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
5498   gst_adapter_flush (demux->adapter, bytes);
5499   demux->neededbytes -= bytes;
5500   demux->offset += bytes;
5501   demux->todrop -= bytes;
5502 }
5503
5504 static GstFlowReturn
5505 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
5506 {
5507   GstQTDemux *demux;
5508
5509   demux = GST_QTDEMUX (parent);
5510
5511   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
5512     gint i;
5513
5514     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
5515
5516     for (i = 0; i < demux->n_streams; i++) {
5517       demux->streams[i]->discont = TRUE;
5518     }
5519
5520     /* Reverse fragmented playback, need to flush all we have before
5521      * consuming a new fragment.
5522      * The samples array have the timestamps calculated by accumulating the
5523      * durations but this won't work for reverse playback of fragments as
5524      * the timestamps of a subsequent fragment should be smaller than the
5525      * previously received one. */
5526     if (demux->fragmented && demux->segment.rate < 0) {
5527       gst_qtdemux_process_adapter (demux, TRUE);
5528       for (i = 0; i < demux->n_streams; i++)
5529         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
5530     }
5531   }
5532
5533   gst_adapter_push (demux->adapter, inbuf);
5534
5535   GST_DEBUG_OBJECT (demux,
5536       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
5537       demux->neededbytes, gst_adapter_available (demux->adapter));
5538
5539   return gst_qtdemux_process_adapter (demux, FALSE);
5540 }
5541
5542 static GstFlowReturn
5543 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
5544 {
5545   GstFlowReturn ret = GST_FLOW_OK;
5546
5547   /* we never really mean to buffer that much */
5548   if (demux->neededbytes == -1) {
5549     goto eos;
5550   }
5551
5552   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
5553       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
5554
5555     GST_DEBUG_OBJECT (demux,
5556         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
5557         demux->state, demux->neededbytes, demux->offset);
5558
5559     switch (demux->state) {
5560       case QTDEMUX_STATE_INITIAL:{
5561         const guint8 *data;
5562         guint32 fourcc;
5563         guint64 size;
5564
5565         gst_qtdemux_check_seekability (demux);
5566
5567         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5568
5569         /* get fourcc/length, set neededbytes */
5570         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
5571             &size, &fourcc);
5572         gst_adapter_unmap (demux->adapter);
5573         data = NULL;
5574         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
5575             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
5576         if (size == 0) {
5577           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5578               (_("This file is invalid and cannot be played.")),
5579               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
5580                   GST_FOURCC_ARGS (fourcc)));
5581           ret = GST_FLOW_ERROR;
5582           break;
5583         }
5584         if (fourcc == FOURCC_mdat) {
5585           gint next_entry = next_entry_size (demux);
5586           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
5587             /* we have the headers, start playback */
5588             demux->state = QTDEMUX_STATE_MOVIE;
5589             demux->neededbytes = next_entry;
5590             demux->mdatleft = size;
5591           } else {
5592             /* no headers yet, try to get them */
5593             guint bs;
5594             gboolean res;
5595             guint64 old, target;
5596
5597           buffer_data:
5598             old = demux->offset;
5599             target = old + size;
5600
5601             /* try to jump over the atom with a seek */
5602             /* only bother if it seems worth doing so,
5603              * and avoids possible upstream/server problems */
5604             if (demux->upstream_seekable &&
5605                 demux->upstream_size > 4 * (1 << 20)) {
5606               res = qtdemux_seek_offset (demux, target);
5607             } else {
5608               GST_DEBUG_OBJECT (demux, "skipping seek");
5609               res = FALSE;
5610             }
5611
5612             if (res) {
5613               GST_DEBUG_OBJECT (demux, "seek success");
5614               /* remember the offset fo the first mdat so we can seek back to it
5615                * after we have the headers */
5616               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
5617                 demux->first_mdat = old;
5618                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
5619                     demux->first_mdat);
5620               }
5621               /* seek worked, continue reading */
5622               demux->offset = target;
5623               demux->neededbytes = 16;
5624               demux->state = QTDEMUX_STATE_INITIAL;
5625             } else {
5626               /* seek failed, need to buffer */
5627               demux->offset = old;
5628               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
5629               /* there may be multiple mdat (or alike) buffers */
5630               /* sanity check */
5631               if (demux->mdatbuffer)
5632                 bs = gst_buffer_get_size (demux->mdatbuffer);
5633               else
5634                 bs = 0;
5635               if (size + bs > 10 * (1 << 20))
5636                 goto no_moov;
5637               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
5638               demux->neededbytes = size;
5639               if (!demux->mdatbuffer)
5640                 demux->mdatoffset = demux->offset;
5641             }
5642           }
5643         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
5644           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5645               (_("This file is invalid and cannot be played.")),
5646               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
5647                   GST_FOURCC_ARGS (fourcc), size));
5648           ret = GST_FLOW_ERROR;
5649           break;
5650         } else {
5651           /* this means we already started buffering and still no moov header,
5652            * let's continue buffering everything till we get moov */
5653           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
5654                   || fourcc == FOURCC_moof))
5655             goto buffer_data;
5656           demux->neededbytes = size;
5657           demux->state = QTDEMUX_STATE_HEADER;
5658         }
5659         break;
5660       }
5661       case QTDEMUX_STATE_HEADER:{
5662         const guint8 *data;
5663         guint32 fourcc;
5664
5665         GST_DEBUG_OBJECT (demux, "In header");
5666
5667         data = gst_adapter_map (demux->adapter, demux->neededbytes);
5668
5669         /* parse the header */
5670         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
5671             &fourcc);
5672         if (fourcc == FOURCC_moov) {
5673           /* in usual fragmented setup we could try to scan for more
5674            * and end up at the the moov (after mdat) again */
5675           if (demux->got_moov && demux->n_streams > 0 &&
5676               (!demux->fragmented
5677                   || demux->last_moov_offset == demux->offset)) {
5678             GST_DEBUG_OBJECT (demux,
5679                 "Skipping moov atom as we have (this) one already");
5680           } else {
5681             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
5682
5683             if (demux->got_moov && demux->fragmented) {
5684               GST_DEBUG_OBJECT (demux,
5685                   "Got a second moov, clean up data from old one");
5686               if (demux->moov_node)
5687                 g_node_destroy (demux->moov_node);
5688               demux->moov_node = NULL;
5689               demux->moov_node_compressed = NULL;
5690             } else {
5691               /* prepare newsegment to send when streaming actually starts */
5692               if (!demux->pending_newsegment)
5693                 demux->pending_newsegment =
5694                     gst_event_new_segment (&demux->segment);
5695             }
5696
5697             demux->last_moov_offset = demux->offset;
5698
5699             qtdemux_parse_moov (demux, data, demux->neededbytes);
5700             qtdemux_node_dump (demux, demux->moov_node);
5701             qtdemux_parse_tree (demux);
5702             qtdemux_prepare_streams (demux);
5703             if (!demux->got_moov)
5704               qtdemux_expose_streams (demux);
5705             else {
5706               gint n;
5707
5708               for (n = 0; n < demux->n_streams; n++) {
5709                 QtDemuxStream *stream = demux->streams[n];
5710
5711                 gst_qtdemux_configure_stream (demux, stream);
5712               }
5713             }
5714
5715             demux->got_moov = TRUE;
5716
5717             g_node_destroy (demux->moov_node);
5718             demux->moov_node = NULL;
5719             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
5720           }
5721         } else if (fourcc == FOURCC_moof) {
5722           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
5723             guint64 dist = 0;
5724             GstClockTime prev_pts;
5725             guint64 prev_offset;
5726
5727             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
5728
5729             /*
5730              * The timestamp of the moof buffer is relevant as some scenarios
5731              * won't have the initial timestamp in the atoms. Whenever a new
5732              * buffer has started, we get that buffer's PTS and use it as a base
5733              * timestamp for the trun entries.
5734              *
5735              * To keep track of the current buffer timestamp and starting point
5736              * we use gst_adapter_prev_pts that gives us the PTS and the distance
5737              * from the beggining of the buffer, with the distance and demux->offset
5738              * we know if it is still the same buffer or not.
5739              */
5740             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
5741             prev_offset = demux->offset - dist;
5742             if (demux->fragment_start_offset == -1
5743                 || prev_offset > demux->fragment_start_offset) {
5744               demux->fragment_start_offset = prev_offset;
5745               demux->fragment_start = prev_pts;
5746               GST_DEBUG_OBJECT (demux,
5747                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
5748                   GST_TIME_FORMAT, demux->fragment_start_offset,
5749                   GST_TIME_ARGS (demux->fragment_start));
5750             }
5751
5752             demux->moof_offset = demux->offset;
5753             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
5754                     demux->offset, NULL)) {
5755               gst_adapter_unmap (demux->adapter);
5756               ret = GST_FLOW_ERROR;
5757               goto done;
5758             }
5759             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
5760             if (demux->mss_mode && !demux->exposed) {
5761               if (!demux->pending_newsegment) {
5762                 GstSegment segment;
5763                 gst_segment_init (&segment, GST_FORMAT_TIME);
5764                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
5765                 demux->pending_newsegment = gst_event_new_segment (&segment);
5766               }
5767               qtdemux_expose_streams (demux);
5768             }
5769           } else {
5770             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
5771           }
5772         } else if (fourcc == FOURCC_ftyp) {
5773           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
5774           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
5775         } else if (fourcc == FOURCC_uuid) {
5776           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
5777           qtdemux_parse_uuid (demux, data, demux->neededbytes);
5778         } else if (fourcc == FOURCC_sidx) {
5779           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
5780           qtdemux_parse_sidx (demux, data, demux->neededbytes);
5781         } else {
5782           GST_WARNING_OBJECT (demux,
5783               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
5784               GST_FOURCC_ARGS (fourcc));
5785           /* Let's jump that one and go back to initial state */
5786         }
5787         gst_adapter_unmap (demux->adapter);
5788         data = NULL;
5789
5790         if (demux->mdatbuffer && demux->n_streams) {
5791           gsize remaining_data_size = 0;
5792
5793           /* the mdat was before the header */
5794           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
5795               demux->n_streams, demux->mdatbuffer);
5796           /* restore our adapter/offset view of things with upstream;
5797            * put preceding buffered data ahead of current moov data.
5798            * This should also handle evil mdat, moov, mdat cases and alike */
5799           gst_adapter_flush (demux->adapter, demux->neededbytes);
5800
5801           /* Store any remaining data after the mdat for later usage */
5802           remaining_data_size = gst_adapter_available (demux->adapter);
5803           if (remaining_data_size > 0) {
5804             g_assert (demux->restoredata_buffer == NULL);
5805             demux->restoredata_buffer =
5806                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
5807             demux->restoredata_offset = demux->offset + demux->neededbytes;
5808             GST_DEBUG_OBJECT (demux,
5809                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
5810                 G_GUINT64_FORMAT, remaining_data_size,
5811                 demux->restoredata_offset);
5812           }
5813
5814           gst_adapter_push (demux->adapter, demux->mdatbuffer);
5815           demux->mdatbuffer = NULL;
5816           demux->offset = demux->mdatoffset;
5817           demux->neededbytes = next_entry_size (demux);
5818           demux->state = QTDEMUX_STATE_MOVIE;
5819           demux->mdatleft = gst_adapter_available (demux->adapter);
5820         } else {
5821           GST_DEBUG_OBJECT (demux, "Carrying on normally");
5822           gst_adapter_flush (demux->adapter, demux->neededbytes);
5823
5824           /* only go back to the mdat if there are samples to play */
5825           if (demux->got_moov && demux->first_mdat != -1
5826               && has_next_entry (demux)) {
5827             gboolean res;
5828
5829             /* we need to seek back */
5830             res = qtdemux_seek_offset (demux, demux->first_mdat);
5831             if (res) {
5832               demux->offset = demux->first_mdat;
5833             } else {
5834               GST_DEBUG_OBJECT (demux, "Seek back failed");
5835             }
5836           } else {
5837             demux->offset += demux->neededbytes;
5838           }
5839           demux->neededbytes = 16;
5840           demux->state = QTDEMUX_STATE_INITIAL;
5841         }
5842
5843         break;
5844       }
5845       case QTDEMUX_STATE_BUFFER_MDAT:{
5846         GstBuffer *buf;
5847         guint8 fourcc[4];
5848
5849         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
5850             demux->offset);
5851         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
5852         gst_buffer_extract (buf, 0, fourcc, 4);
5853         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
5854             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
5855         if (demux->mdatbuffer)
5856           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
5857         else
5858           demux->mdatbuffer = buf;
5859         demux->offset += demux->neededbytes;
5860         demux->neededbytes = 16;
5861         demux->state = QTDEMUX_STATE_INITIAL;
5862         gst_qtdemux_post_progress (demux, 1, 1);
5863
5864         break;
5865       }
5866       case QTDEMUX_STATE_MOVIE:{
5867         QtDemuxStream *stream = NULL;
5868         QtDemuxSample *sample;
5869         int i = -1;
5870         GstClockTime dts, pts, duration;
5871         gboolean keyframe;
5872
5873         GST_DEBUG_OBJECT (demux,
5874             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
5875
5876         if (demux->fragmented) {
5877           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
5878               demux->mdatleft);
5879           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
5880             /* if needed data starts within this atom,
5881              * then it should not exceed this atom */
5882             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
5883               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
5884                   (_("This file is invalid and cannot be played.")),
5885                   ("sample data crosses atom boundary"));
5886               ret = GST_FLOW_ERROR;
5887               break;
5888             }
5889             demux->mdatleft -= demux->neededbytes;
5890           } else {
5891             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
5892             /* so we are dropping more than left in this atom */
5893             gst_qtdemux_drop_data (demux, demux->mdatleft);
5894             demux->mdatleft = 0;
5895
5896             /* need to resume atom parsing so we do not miss any other pieces */
5897             demux->state = QTDEMUX_STATE_INITIAL;
5898             demux->neededbytes = 16;
5899
5900             /* check if there was any stored post mdat data from previous buffers */
5901             if (demux->restoredata_buffer) {
5902               g_assert (gst_adapter_available (demux->adapter) == 0);
5903
5904               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
5905               demux->restoredata_buffer = NULL;
5906               demux->offset = demux->restoredata_offset;
5907             }
5908
5909             break;
5910           }
5911         }
5912
5913         if (demux->todrop) {
5914           gst_qtdemux_drop_data (demux, demux->todrop);
5915         }
5916
5917         /* first buffer? */
5918         /* initial newsegment sent here after having added pads,
5919          * possible others in sink_event */
5920         if (G_UNLIKELY (demux->pending_newsegment)) {
5921           gst_qtdemux_push_pending_newsegment (demux);
5922           /* clear to send tags on all streams */
5923           for (i = 0; i < demux->n_streams; i++) {
5924             stream = demux->streams[i];
5925             gst_qtdemux_push_tags (demux, stream);
5926             if (stream->sparse) {
5927               GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
5928               gst_pad_push_event (stream->pad,
5929                   gst_event_new_gap (stream->segment.position,
5930                       GST_CLOCK_TIME_NONE));
5931             }
5932           }
5933         }
5934
5935         /* Figure out which stream this packet belongs to */
5936         for (i = 0; i < demux->n_streams; i++) {
5937           stream = demux->streams[i];
5938           if (stream->sample_index >= stream->n_samples)
5939             continue;
5940           GST_LOG_OBJECT (demux,
5941               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
5942               " / size:%d)", i, stream->sample_index,
5943               stream->samples[stream->sample_index].offset,
5944               stream->samples[stream->sample_index].size);
5945
5946           if (stream->samples[stream->sample_index].offset == demux->offset)
5947             break;
5948         }
5949
5950         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
5951           goto unknown_stream;
5952
5953         if (stream->new_caps) {
5954           gst_qtdemux_configure_stream (demux, stream);
5955         }
5956
5957         /* Put data in a buffer, set timestamps, caps, ... */
5958         sample = &stream->samples[stream->sample_index];
5959
5960         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
5961           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
5962               GST_FOURCC_ARGS (stream->fourcc));
5963
5964           dts = QTSAMPLE_DTS (stream, sample);
5965           pts = QTSAMPLE_PTS (stream, sample);
5966           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
5967           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5968
5969           /* check for segment end */
5970           if (G_UNLIKELY (demux->segment.stop != -1
5971                   && demux->segment.stop <= pts && stream->on_keyframe)) {
5972             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
5973             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
5974
5975             /* skip this data, stream is EOS */
5976             gst_adapter_flush (demux->adapter, demux->neededbytes);
5977
5978             /* check if all streams are eos */
5979             ret = GST_FLOW_EOS;
5980             for (i = 0; i < demux->n_streams; i++) {
5981               if (!STREAM_IS_EOS (demux->streams[i])) {
5982                 ret = GST_FLOW_OK;
5983                 break;
5984               }
5985             }
5986
5987             if (ret == GST_FLOW_EOS) {
5988               GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
5989               goto eos;
5990             }
5991           } else {
5992             GstBuffer *outbuf;
5993
5994             outbuf =
5995                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
5996
5997             /* FIXME: should either be an assert or a plain check */
5998             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
5999
6000             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6001                 dts, pts, duration, keyframe, dts, demux->offset);
6002           }
6003
6004           /* combine flows */
6005           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6006         } else {
6007           /* skip this data, stream is EOS */
6008           gst_adapter_flush (demux->adapter, demux->neededbytes);
6009         }
6010
6011         stream->sample_index++;
6012         stream->offset_in_sample = 0;
6013
6014         /* update current offset and figure out size of next buffer */
6015         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6016             demux->offset, demux->neededbytes);
6017         demux->offset += demux->neededbytes;
6018         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6019             demux->offset);
6020
6021         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6022           if (demux->fragmented) {
6023             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6024             /* there may be more to follow, only finish this atom */
6025             demux->todrop = demux->mdatleft;
6026             demux->neededbytes = demux->todrop;
6027             break;
6028           }
6029           goto eos;
6030         }
6031         break;
6032       }
6033       default:
6034         goto invalid_state;
6035     }
6036   }
6037
6038   /* when buffering movie data, at least show user something is happening */
6039   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6040       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6041     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6042         demux->neededbytes);
6043   }
6044 done:
6045
6046   return ret;
6047
6048   /* ERRORS */
6049 unknown_stream:
6050   {
6051     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6052     ret = GST_FLOW_ERROR;
6053     goto done;
6054   }
6055 eos:
6056   {
6057     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
6058     ret = GST_FLOW_EOS;
6059     goto done;
6060   }
6061 invalid_state:
6062   {
6063     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6064         (NULL), ("qtdemuxer invalid state %d", demux->state));
6065     ret = GST_FLOW_ERROR;
6066     goto done;
6067   }
6068 no_moov:
6069   {
6070     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
6071         (NULL), ("no 'moov' atom within the first 10 MB"));
6072     ret = GST_FLOW_ERROR;
6073     goto done;
6074   }
6075 }
6076
6077 static gboolean
6078 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
6079 {
6080   GstQuery *query;
6081   gboolean pull_mode;
6082
6083   query = gst_query_new_scheduling ();
6084
6085   if (!gst_pad_peer_query (sinkpad, query)) {
6086     gst_query_unref (query);
6087     goto activate_push;
6088   }
6089
6090   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
6091       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
6092   gst_query_unref (query);
6093
6094   if (!pull_mode)
6095     goto activate_push;
6096
6097   GST_DEBUG_OBJECT (sinkpad, "activating pull");
6098   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
6099
6100 activate_push:
6101   {
6102     GST_DEBUG_OBJECT (sinkpad, "activating push");
6103     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
6104   }
6105 }
6106
6107 static gboolean
6108 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
6109     GstPadMode mode, gboolean active)
6110 {
6111   gboolean res;
6112   GstQTDemux *demux = GST_QTDEMUX (parent);
6113
6114   switch (mode) {
6115     case GST_PAD_MODE_PUSH:
6116       demux->pullbased = FALSE;
6117       res = TRUE;
6118       break;
6119     case GST_PAD_MODE_PULL:
6120       if (active) {
6121         demux->pullbased = TRUE;
6122         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
6123             sinkpad, NULL);
6124       } else {
6125         res = gst_pad_stop_task (sinkpad);
6126       }
6127       break;
6128     default:
6129       res = FALSE;
6130       break;
6131   }
6132   return res;
6133 }
6134
6135 #ifdef HAVE_ZLIB
6136 static void *
6137 qtdemux_zalloc (void *opaque, unsigned int items, unsigned int size)
6138 {
6139   return g_malloc (items * size);
6140 }
6141
6142 static void
6143 qtdemux_zfree (void *opaque, void *addr)
6144 {
6145   g_free (addr);
6146 }
6147
6148 static void *
6149 qtdemux_inflate (void *z_buffer, guint z_length, guint length)
6150 {
6151   guint8 *buffer;
6152   z_stream *z;
6153   int ret;
6154
6155   z = g_new0 (z_stream, 1);
6156   z->zalloc = qtdemux_zalloc;
6157   z->zfree = qtdemux_zfree;
6158   z->opaque = NULL;
6159
6160   z->next_in = z_buffer;
6161   z->avail_in = z_length;
6162
6163   buffer = (guint8 *) g_malloc (length);
6164   ret = inflateInit (z);
6165   while (z->avail_in > 0) {
6166     if (z->avail_out == 0) {
6167       length += 1024;
6168       buffer = (guint8 *) g_realloc (buffer, length);
6169       z->next_out = buffer + z->total_out;
6170       z->avail_out = 1024;
6171     }
6172     ret = inflate (z, Z_SYNC_FLUSH);
6173     if (ret != Z_OK)
6174       break;
6175   }
6176   if (ret != Z_STREAM_END) {
6177     g_warning ("inflate() returned %d", ret);
6178   }
6179
6180   g_free (z);
6181   return buffer;
6182 }
6183 #endif /* HAVE_ZLIB */
6184
6185 static gboolean
6186 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
6187 {
6188   GNode *cmov;
6189
6190   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
6191
6192   /* counts as header data */
6193   qtdemux->header_size += length;
6194
6195   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
6196   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
6197
6198   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
6199   if (cmov) {
6200     guint32 method;
6201     GNode *dcom;
6202     GNode *cmvd;
6203
6204     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
6205     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
6206     if (dcom == NULL || cmvd == NULL)
6207       goto invalid_compression;
6208
6209     method = QT_FOURCC ((guint8 *) dcom->data + 8);
6210     switch (method) {
6211 #ifdef HAVE_ZLIB
6212       case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
6213         guint uncompressed_length;
6214         guint compressed_length;
6215         guint8 *buf;
6216
6217         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
6218         compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
6219         GST_LOG ("length = %u", uncompressed_length);
6220
6221         buf =
6222             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
6223             compressed_length, uncompressed_length);
6224
6225         qtdemux->moov_node_compressed = qtdemux->moov_node;
6226         qtdemux->moov_node = g_node_new (buf);
6227
6228         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
6229             uncompressed_length);
6230         break;
6231       }
6232 #endif /* HAVE_ZLIB */
6233       default:
6234         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
6235             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
6236         break;
6237     }
6238   }
6239   return TRUE;
6240
6241   /* ERRORS */
6242 invalid_compression:
6243   {
6244     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
6245     return FALSE;
6246   }
6247 }
6248
6249 static gboolean
6250 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
6251     const guint8 * end)
6252 {
6253   while (G_UNLIKELY (buf < end)) {
6254     GNode *child;
6255     guint32 len;
6256
6257     if (G_UNLIKELY (buf + 4 > end)) {
6258       GST_LOG_OBJECT (qtdemux, "buffer overrun");
6259       break;
6260     }
6261     len = QT_UINT32 (buf);
6262     if (G_UNLIKELY (len == 0)) {
6263       GST_LOG_OBJECT (qtdemux, "empty container");
6264       break;
6265     }
6266     if (G_UNLIKELY (len < 8)) {
6267       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
6268       break;
6269     }
6270     if (G_UNLIKELY (len > (end - buf))) {
6271       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
6272           (gint) (end - buf));
6273       break;
6274     }
6275
6276     child = g_node_new ((guint8 *) buf);
6277     g_node_append (node, child);
6278     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
6279     qtdemux_parse_node (qtdemux, child, buf, len);
6280
6281     buf += len;
6282   }
6283   return TRUE;
6284 }
6285
6286 static gboolean
6287 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
6288     GNode * xdxt)
6289 {
6290   int len = QT_UINT32 (xdxt->data);
6291   guint8 *buf = xdxt->data;
6292   guint8 *end = buf + len;
6293   GstBuffer *buffer;
6294
6295   /* skip size and type */
6296   buf += 8;
6297   end -= 8;
6298
6299   while (buf < end) {
6300     gint size;
6301     guint32 type;
6302
6303     size = QT_UINT32 (buf);
6304     type = QT_FOURCC (buf + 4);
6305
6306     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
6307
6308     if (buf + size > end || size <= 0)
6309       break;
6310
6311     buf += 8;
6312     size -= 8;
6313
6314     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
6315         GST_FOURCC_ARGS (type));
6316
6317     switch (type) {
6318       case FOURCC_tCtH:
6319         buffer = gst_buffer_new_and_alloc (size);
6320         gst_buffer_fill (buffer, 0, buf, size);
6321         stream->buffers = g_slist_append (stream->buffers, buffer);
6322         GST_LOG_OBJECT (qtdemux, "parsing theora header");
6323         break;
6324       case FOURCC_tCt_:
6325         buffer = gst_buffer_new_and_alloc (size);
6326         gst_buffer_fill (buffer, 0, buf, size);
6327         stream->buffers = g_slist_append (stream->buffers, buffer);
6328         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
6329         break;
6330       case FOURCC_tCtC:
6331         buffer = gst_buffer_new_and_alloc (size);
6332         gst_buffer_fill (buffer, 0, buf, size);
6333         stream->buffers = g_slist_append (stream->buffers, buffer);
6334         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
6335         break;
6336       default:
6337         GST_WARNING_OBJECT (qtdemux,
6338             "unknown theora cookie %" GST_FOURCC_FORMAT,
6339             GST_FOURCC_ARGS (type));
6340         break;
6341     }
6342     buf += size;
6343   }
6344   return TRUE;
6345 }
6346
6347 static gboolean
6348 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
6349     guint length)
6350 {
6351   guint32 fourcc = 0;
6352   guint32 node_length = 0;
6353   const QtNodeType *type;
6354   const guint8 *end;
6355
6356   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
6357
6358   if (G_UNLIKELY (length < 8))
6359     goto not_enough_data;
6360
6361   node_length = QT_UINT32 (buffer);
6362   fourcc = QT_FOURCC (buffer + 4);
6363
6364   /* ignore empty nodes */
6365   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
6366     return TRUE;
6367
6368   type = qtdemux_type_get (fourcc);
6369
6370   end = buffer + length;
6371
6372   GST_LOG_OBJECT (qtdemux,
6373       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
6374       GST_FOURCC_ARGS (fourcc), node_length, type->name);
6375
6376   if (node_length > length)
6377     goto broken_atom_size;
6378
6379   if (type->flags & QT_FLAG_CONTAINER) {
6380     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
6381   } else {
6382     switch (fourcc) {
6383       case FOURCC_stsd:
6384       {
6385         if (node_length < 20) {
6386           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
6387           break;
6388         }
6389         GST_DEBUG_OBJECT (qtdemux,
6390             "parsing stsd (sample table, sample description) atom");
6391         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
6392         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6393         break;
6394       }
6395       case FOURCC_mp4a:
6396       case FOURCC_alac:
6397       {
6398         guint32 version;
6399         guint32 offset;
6400         guint min_size;
6401
6402         /* also read alac (or whatever) in stead of mp4a in the following,
6403          * since a similar layout is used in other cases as well */
6404         if (fourcc == FOURCC_mp4a)
6405           min_size = 20;
6406         else
6407           min_size = 40;
6408
6409         /* There are two things we might encounter here: a true mp4a atom, and
6410            an mp4a entry in an stsd atom. The latter is what we're interested
6411            in, and it looks like an atom, but isn't really one. The true mp4a
6412            atom is short, so we detect it based on length here. */
6413         if (length < min_size) {
6414           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
6415               GST_FOURCC_ARGS (fourcc));
6416           break;
6417         }
6418
6419         /* 'version' here is the sound sample description version. Types 0 and
6420            1 are documented in the QTFF reference, but type 2 is not: it's
6421            described in Apple header files instead (struct SoundDescriptionV2
6422            in Movies.h) */
6423         version = QT_UINT16 (buffer + 16);
6424
6425         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
6426             GST_FOURCC_ARGS (fourcc), version);
6427
6428         /* parse any esds descriptors */
6429         switch (version) {
6430           case 0:
6431             offset = 0x24;
6432             break;
6433           case 1:
6434             offset = 0x34;
6435             break;
6436           case 2:
6437             offset = 0x48;
6438             break;
6439           default:
6440             GST_WARNING_OBJECT (qtdemux,
6441                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
6442                 GST_FOURCC_ARGS (fourcc), version);
6443             offset = 0;
6444             break;
6445         }
6446         if (offset)
6447           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6448         break;
6449       }
6450       case FOURCC_mp4v:
6451       case FOURCC_MP4V:
6452       case FOURCC_fmp4:
6453       case FOURCC_FMP4:
6454       case FOURCC_apcs:
6455       case FOURCC_apch:
6456       case FOURCC_apcn:
6457       case FOURCC_apco:
6458       case FOURCC_ap4h:
6459       {
6460         const guint8 *buf;
6461         guint32 version;
6462         int tlen;
6463
6464         /* codec_data is contained inside these atoms, which all have
6465          * the same format. */
6466
6467         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
6468             GST_FOURCC_ARGS (fourcc));
6469         version = QT_UINT32 (buffer + 16);
6470         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
6471         if (1 || version == 0x00000000) {
6472           buf = buffer + 0x32;
6473
6474           /* FIXME Quicktime uses PASCAL string while
6475            * the iso format uses C strings. Check the file
6476            * type before attempting to parse the string here. */
6477           tlen = QT_UINT8 (buf);
6478           GST_DEBUG_OBJECT (qtdemux, "tlen = %d", tlen);
6479           buf++;
6480           GST_DEBUG_OBJECT (qtdemux, "string = %.*s", tlen, (char *) buf);
6481           /* the string has a reserved space of 32 bytes so skip
6482            * the remaining 31 */
6483           buf += 31;
6484           buf += 4;             /* and 4 bytes reserved */
6485
6486           GST_MEMDUMP_OBJECT (qtdemux, "mp4v", buf, end - buf);
6487
6488           qtdemux_parse_container (qtdemux, node, buf, end);
6489         }
6490         break;
6491       }
6492       case FOURCC_H264:
6493       {
6494         GST_MEMDUMP_OBJECT (qtdemux, "H264", buffer, end - buffer);
6495         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6496         break;
6497       }
6498       case FOURCC_avc1:
6499       {
6500         GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
6501         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6502         break;
6503       }
6504       case FOURCC_avc3:
6505       {
6506         GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer);
6507         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6508         break;
6509       }
6510       case FOURCC_H265:
6511       {
6512         GST_MEMDUMP_OBJECT (qtdemux, "H265", buffer, end - buffer);
6513         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6514         break;
6515       }
6516       case FOURCC_hvc1:
6517       {
6518         GST_MEMDUMP_OBJECT (qtdemux, "hvc1", buffer, end - buffer);
6519         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6520         break;
6521       }
6522       case FOURCC_hev1:
6523       {
6524         GST_MEMDUMP_OBJECT (qtdemux, "hev1", buffer, end - buffer);
6525         qtdemux_parse_container (qtdemux, node, buffer + 0x56, end);
6526         break;
6527       }
6528       case FOURCC_mjp2:
6529       {
6530         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6531         break;
6532       }
6533       case FOURCC_meta:
6534       {
6535         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
6536         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
6537         break;
6538       }
6539       case FOURCC_mp4s:
6540       {
6541         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
6542         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
6543         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
6544         break;
6545       }
6546       case FOURCC_XiTh:
6547       {
6548         guint32 version;
6549         guint32 offset;
6550
6551         version = QT_UINT32 (buffer + 12);
6552         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
6553
6554         switch (version) {
6555           case 0x00000001:
6556             offset = 0x62;
6557             break;
6558           default:
6559             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
6560             offset = 0;
6561             break;
6562         }
6563         if (offset)
6564           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
6565         break;
6566       }
6567       case FOURCC_in24:
6568       {
6569         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
6570         break;
6571       }
6572       case FOURCC_uuid:
6573       {
6574         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
6575         break;
6576       }
6577       case FOURCC_encv:
6578       {
6579         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
6580         break;
6581       }
6582       case FOURCC_enca:
6583       {
6584         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
6585         break;
6586       }
6587       default:
6588         if (!strcmp (type->name, "unknown"))
6589           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
6590         break;
6591     }
6592   }
6593   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
6594       GST_FOURCC_ARGS (fourcc));
6595   return TRUE;
6596
6597 /* ERRORS */
6598 not_enough_data:
6599   {
6600     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6601         (_("This file is corrupt and cannot be played.")),
6602         ("Not enough data for an atom header, got only %u bytes", length));
6603     return FALSE;
6604   }
6605 broken_atom_size:
6606   {
6607     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
6608         (_("This file is corrupt and cannot be played.")),
6609         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
6610             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
6611             length));
6612     return FALSE;
6613   }
6614 }
6615
6616 static GNode *
6617 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
6618 {
6619   GNode *child;
6620   guint8 *buffer;
6621   guint32 child_fourcc;
6622
6623   for (child = g_node_first_child (node); child;
6624       child = g_node_next_sibling (child)) {
6625     buffer = (guint8 *) child->data;
6626
6627     child_fourcc = QT_FOURCC (buffer + 4);
6628
6629     if (G_UNLIKELY (child_fourcc == fourcc)) {
6630       return child;
6631     }
6632   }
6633   return NULL;
6634 }
6635
6636 static GNode *
6637 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
6638     GstByteReader * parser)
6639 {
6640   GNode *child;
6641   guint8 *buffer;
6642   guint32 child_fourcc, child_len;
6643
6644   for (child = g_node_first_child (node); child;
6645       child = g_node_next_sibling (child)) {
6646     buffer = (guint8 *) child->data;
6647
6648     child_len = QT_UINT32 (buffer);
6649     child_fourcc = QT_FOURCC (buffer + 4);
6650
6651     if (G_UNLIKELY (child_fourcc == fourcc)) {
6652       if (G_UNLIKELY (child_len < (4 + 4)))
6653         return NULL;
6654       /* FIXME: must verify if atom length < parent atom length */
6655       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6656       return child;
6657     }
6658   }
6659   return NULL;
6660 }
6661
6662 static GNode *
6663 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
6664     GstByteReader * parser)
6665 {
6666   GNode *child;
6667   guint8 *buffer;
6668   guint32 child_fourcc, child_len;
6669
6670   for (child = g_node_next_sibling (node); child;
6671       child = g_node_next_sibling (child)) {
6672     buffer = (guint8 *) child->data;
6673
6674     child_fourcc = QT_FOURCC (buffer + 4);
6675
6676     if (child_fourcc == fourcc) {
6677       if (parser) {
6678         child_len = QT_UINT32 (buffer);
6679         if (G_UNLIKELY (child_len < (4 + 4)))
6680           return NULL;
6681         /* FIXME: must verify if atom length < parent atom length */
6682         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
6683       }
6684       return child;
6685     }
6686   }
6687   return NULL;
6688 }
6689
6690 static GNode *
6691 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
6692 {
6693   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
6694 }
6695
6696 static void
6697 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
6698 {
6699 /* FIXME: This can only reliably work if demuxers have a
6700  * separate streaming thread per srcpad. This should be
6701  * done in a demuxer base class, which integrates parts
6702  * of multiqueue
6703  *
6704  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
6705  */
6706 #if 0
6707   GstQuery *query;
6708
6709   query = gst_query_new_allocation (stream->caps, FALSE);
6710
6711   if (!gst_pad_peer_query (stream->pad, query)) {
6712     /* not a problem, just debug a little */
6713     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
6714   }
6715
6716   if (stream->allocator)
6717     gst_object_unref (stream->allocator);
6718
6719   if (gst_query_get_n_allocation_params (query) > 0) {
6720     /* try the allocator */
6721     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
6722         &stream->params);
6723     stream->use_allocator = TRUE;
6724   } else {
6725     stream->allocator = NULL;
6726     gst_allocation_params_init (&stream->params);
6727     stream->use_allocator = FALSE;
6728   }
6729   gst_query_unref (query);
6730 #endif
6731 }
6732
6733 static gboolean
6734 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
6735     QtDemuxStream * stream)
6736 {
6737   GstStructure *s;
6738   const gchar *selected_system;
6739
6740   g_return_val_if_fail (qtdemux != NULL, FALSE);
6741   g_return_val_if_fail (stream != NULL, FALSE);
6742   g_return_val_if_fail (gst_caps_get_size (stream->caps) == 1, FALSE);
6743
6744   if (stream->protection_scheme_type != FOURCC_cenc) {
6745     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
6746     return FALSE;
6747   }
6748   if (qtdemux->protection_system_ids == NULL) {
6749     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
6750         "cenc protection system information has been found");
6751     return FALSE;
6752   }
6753   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
6754   selected_system = gst_protection_select_system ((const gchar **)
6755       qtdemux->protection_system_ids->pdata);
6756   g_ptr_array_remove_index (qtdemux->protection_system_ids,
6757       qtdemux->protection_system_ids->len - 1);
6758   if (!selected_system) {
6759     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
6760         "suitable decryptor element has been found");
6761     return FALSE;
6762   }
6763
6764   s = gst_caps_get_structure (stream->caps, 0);
6765   gst_structure_set (s,
6766       "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
6767       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
6768       NULL);
6769   gst_structure_set_name (s, "application/x-cenc");
6770   return TRUE;
6771 }
6772
6773 static gboolean
6774 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
6775 {
6776   if (stream->subtype == FOURCC_vide) {
6777     /* fps is calculated base on the duration of the average framerate since
6778      * qt does not have a fixed framerate. */
6779     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
6780       /* still frame */
6781       stream->fps_n = 0;
6782       stream->fps_d = 1;
6783     } else {
6784       if (stream->duration == 0 || stream->n_samples < 2) {
6785         stream->fps_n = stream->timescale;
6786         stream->fps_d = 1;
6787       } else {
6788         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
6789         /* stream->duration is guint64, timescale, n_samples are guint32 */
6790         GstClockTime avg_duration =
6791             gst_util_uint64_scale_round (stream->duration -
6792             stream->first_duration, GST_SECOND,
6793             (guint64) (stream->timescale) * (stream->n_samples - 1));
6794
6795         GST_LOG_OBJECT (qtdemux,
6796             "Calculating avg sample duration based on stream duration %"
6797             G_GUINT64_FORMAT
6798             " minus first sample %u, leaving %d samples gives %"
6799             GST_TIME_FORMAT, stream->duration, stream->first_duration,
6800             stream->n_samples - 1, GST_TIME_ARGS (avg_duration));
6801
6802         gst_video_guess_framerate (avg_duration, &stream->fps_n,
6803             &stream->fps_d);
6804       }
6805       GST_DEBUG_OBJECT (qtdemux,
6806           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
6807           stream->timescale, stream->fps_n, stream->fps_d);
6808     }
6809
6810     if (stream->caps) {
6811       stream->caps = gst_caps_make_writable (stream->caps);
6812
6813       gst_caps_set_simple (stream->caps,
6814           "width", G_TYPE_INT, stream->width,
6815           "height", G_TYPE_INT, stream->height,
6816           "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
6817
6818       /* calculate pixel-aspect-ratio using display width and height */
6819       GST_DEBUG_OBJECT (qtdemux,
6820           "video size %dx%d, target display size %dx%d", stream->width,
6821           stream->height, stream->display_width, stream->display_height);
6822       /* qt file might have pasp atom */
6823       if (stream->par_w > 0 && stream->par_h > 0) {
6824         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
6825         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6826             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6827       } else if (stream->display_width > 0 && stream->display_height > 0 &&
6828           stream->width > 0 && stream->height > 0) {
6829         gint n, d;
6830
6831         /* calculate the pixel aspect ratio using the display and pixel w/h */
6832         n = stream->display_width * stream->height;
6833         d = stream->display_height * stream->width;
6834         if (n == d)
6835           n = d = 1;
6836         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
6837         stream->par_w = n;
6838         stream->par_h = d;
6839         gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
6840             GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
6841       }
6842
6843       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
6844         guint par_w = 1, par_h = 1;
6845
6846         if (stream->par_w > 0 && stream->par_h > 0) {
6847           par_w = stream->par_w;
6848           par_h = stream->par_h;
6849         }
6850
6851         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
6852                 stream->width, stream->height, par_w, par_h)) {
6853           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
6854         }
6855
6856         gst_caps_set_simple (stream->caps,
6857             "multiview-mode", G_TYPE_STRING,
6858             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
6859             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
6860             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
6861       }
6862     }
6863   }
6864
6865   else if (stream->subtype == FOURCC_soun) {
6866     if (stream->caps) {
6867       stream->caps = gst_caps_make_writable (stream->caps);
6868       if (stream->rate > 0)
6869         gst_caps_set_simple (stream->caps,
6870             "rate", G_TYPE_INT, (int) stream->rate, NULL);
6871       if (stream->n_channels > 0)
6872         gst_caps_set_simple (stream->caps,
6873             "channels", G_TYPE_INT, stream->n_channels, NULL);
6874       if (stream->n_channels > 2) {
6875         /* FIXME: Need to parse the 'chan' atom to get channel layouts
6876          * correctly; this is just the minimum we can do - assume
6877          * we don't actually have any channel positions. */
6878         gst_caps_set_simple (stream->caps,
6879             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
6880       }
6881     }
6882   }
6883
6884   if (stream->pad) {
6885     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
6886     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
6887     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
6888     gst_pad_set_active (stream->pad, TRUE);
6889
6890     gst_pad_use_fixed_caps (stream->pad);
6891
6892     if (stream->protected) {
6893       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
6894         GST_ERROR_OBJECT (qtdemux,
6895             "Failed to configure protected stream caps.");
6896         return FALSE;
6897       }
6898     }
6899
6900     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
6901     if (stream->new_stream) {
6902       gchar *stream_id;
6903       GstEvent *event;
6904       GstStreamFlags stream_flags;
6905
6906       event =
6907           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
6908           0);
6909       if (event) {
6910         if (gst_event_parse_group_id (event, &qtdemux->group_id))
6911           qtdemux->have_group_id = TRUE;
6912         else
6913           qtdemux->have_group_id = FALSE;
6914         gst_event_unref (event);
6915       } else if (!qtdemux->have_group_id) {
6916         qtdemux->have_group_id = TRUE;
6917         qtdemux->group_id = gst_util_group_id_next ();
6918       }
6919
6920       stream->new_stream = FALSE;
6921       stream_id =
6922           gst_pad_create_stream_id_printf (stream->pad,
6923           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
6924       event = gst_event_new_stream_start (stream_id);
6925       if (qtdemux->have_group_id)
6926         gst_event_set_group_id (event, qtdemux->group_id);
6927       stream_flags = GST_STREAM_FLAG_NONE;
6928       if (stream->disabled)
6929         stream_flags |= GST_STREAM_FLAG_UNSELECT;
6930       if (stream->sparse)
6931         stream_flags |= GST_STREAM_FLAG_SPARSE;
6932       gst_event_set_stream_flags (event, stream_flags);
6933       gst_pad_push_event (stream->pad, event);
6934       g_free (stream_id);
6935     }
6936     gst_pad_set_caps (stream->pad, stream->caps);
6937     stream->new_caps = FALSE;
6938   }
6939   return TRUE;
6940 }
6941
6942 static gboolean
6943 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
6944     QtDemuxStream * stream, GstTagList * list)
6945 {
6946   /* consistent default for push based mode */
6947   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
6948
6949   if (stream->subtype == FOURCC_vide) {
6950     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
6951
6952     stream->pad =
6953         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
6954     g_free (name);
6955
6956     gst_qtdemux_configure_stream (qtdemux, stream);
6957     qtdemux->n_video_streams++;
6958   } else if (stream->subtype == FOURCC_soun) {
6959     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
6960
6961     stream->pad =
6962         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
6963     g_free (name);
6964     gst_qtdemux_configure_stream (qtdemux, stream);
6965     qtdemux->n_audio_streams++;
6966   } else if (stream->subtype == FOURCC_strm) {
6967     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
6968   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
6969       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
6970     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
6971
6972     stream->pad =
6973         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
6974     g_free (name);
6975     gst_qtdemux_configure_stream (qtdemux, stream);
6976     qtdemux->n_sub_streams++;
6977   } else if (stream->caps) {
6978     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
6979
6980     stream->pad =
6981         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
6982     g_free (name);
6983     gst_qtdemux_configure_stream (qtdemux, stream);
6984     qtdemux->n_video_streams++;
6985   } else {
6986     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
6987     goto done;
6988   }
6989
6990   if (stream->pad) {
6991     GList *l;
6992
6993     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
6994         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
6995     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
6996     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
6997
6998     if (stream->pending_tags)
6999       gst_tag_list_unref (stream->pending_tags);
7000     stream->pending_tags = list;
7001     list = NULL;
7002     /* global tags go on each pad anyway */
7003     stream->send_global_tags = TRUE;
7004     /* send upstream GST_EVENT_PROTECTION events that were received before
7005        this source pad was created */
7006     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
7007       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
7008   }
7009 done:
7010   if (list)
7011     gst_tag_list_unref (list);
7012   return TRUE;
7013 }
7014
7015 /* find next atom with @fourcc starting at @offset */
7016 static GstFlowReturn
7017 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
7018     guint64 * length, guint32 fourcc)
7019 {
7020   GstFlowReturn ret;
7021   guint32 lfourcc;
7022   GstBuffer *buf;
7023
7024   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
7025       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
7026
7027   while (TRUE) {
7028     GstMapInfo map;
7029
7030     buf = NULL;
7031     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
7032     if (G_UNLIKELY (ret != GST_FLOW_OK))
7033       goto locate_failed;
7034     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
7035       /* likely EOF */
7036       ret = GST_FLOW_EOS;
7037       gst_buffer_unref (buf);
7038       goto locate_failed;
7039     }
7040     gst_buffer_map (buf, &map, GST_MAP_READ);
7041     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
7042     gst_buffer_unmap (buf, &map);
7043     gst_buffer_unref (buf);
7044
7045     if (G_UNLIKELY (*length == 0)) {
7046       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
7047       ret = GST_FLOW_ERROR;
7048       goto locate_failed;
7049     }
7050
7051     if (lfourcc == fourcc) {
7052       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
7053           *offset);
7054       break;
7055     } else {
7056       GST_LOG_OBJECT (qtdemux,
7057           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
7058           GST_FOURCC_ARGS (fourcc), *offset);
7059       *offset += *length;
7060     }
7061   }
7062
7063   return GST_FLOW_OK;
7064
7065 locate_failed:
7066   {
7067     /* might simply have had last one */
7068     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
7069     return ret;
7070   }
7071 }
7072
7073 /* should only do something in pull mode */
7074 /* call with OBJECT lock */
7075 static GstFlowReturn
7076 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
7077 {
7078   guint64 length, offset;
7079   GstBuffer *buf = NULL;
7080   GstFlowReturn ret = GST_FLOW_OK;
7081   GstFlowReturn res = GST_FLOW_OK;
7082   GstMapInfo map;
7083
7084   offset = qtdemux->moof_offset;
7085   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
7086
7087   if (!offset) {
7088     GST_DEBUG_OBJECT (qtdemux, "no next moof");
7089     return GST_FLOW_EOS;
7090   }
7091
7092   /* best not do pull etc with lock held */
7093   GST_OBJECT_UNLOCK (qtdemux);
7094
7095   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7096   if (ret != GST_FLOW_OK)
7097     goto flow_failed;
7098
7099   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
7100   if (G_UNLIKELY (ret != GST_FLOW_OK))
7101     goto flow_failed;
7102   gst_buffer_map (buf, &map, GST_MAP_READ);
7103   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
7104     gst_buffer_unmap (buf, &map);
7105     gst_buffer_unref (buf);
7106     buf = NULL;
7107     goto parse_failed;
7108   }
7109
7110   gst_buffer_unmap (buf, &map);
7111   gst_buffer_unref (buf);
7112   buf = NULL;
7113
7114   offset += length;
7115   /* look for next moof */
7116   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
7117   if (G_UNLIKELY (ret != GST_FLOW_OK))
7118     goto flow_failed;
7119
7120 exit:
7121   GST_OBJECT_LOCK (qtdemux);
7122
7123   qtdemux->moof_offset = offset;
7124
7125   return res;
7126
7127 parse_failed:
7128   {
7129     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
7130     offset = 0;
7131     res = GST_FLOW_ERROR;
7132     goto exit;
7133   }
7134 flow_failed:
7135   {
7136     /* maybe upstream temporarily flushing */
7137     if (ret != GST_FLOW_FLUSHING) {
7138       GST_DEBUG_OBJECT (qtdemux, "no next moof");
7139       offset = 0;
7140     } else {
7141       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
7142       /* resume at current position next time */
7143     }
7144     res = ret;
7145     goto exit;
7146   }
7147 }
7148
7149 /* initialise bytereaders for stbl sub-atoms */
7150 static gboolean
7151 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
7152 {
7153   stream->stbl_index = -1;      /* no samples have yet been parsed */
7154   stream->sample_index = -1;
7155
7156   /* time-to-sample atom */
7157   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
7158     goto corrupt_file;
7159
7160   /* copy atom data into a new buffer for later use */
7161   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
7162
7163   /* skip version + flags */
7164   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
7165       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
7166     goto corrupt_file;
7167   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
7168
7169   /* make sure there's enough data */
7170   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
7171     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
7172     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
7173         stream->n_sample_times);
7174     if (!stream->n_sample_times)
7175       goto corrupt_file;
7176   }
7177
7178   /* sync sample atom */
7179   stream->stps_present = FALSE;
7180   if ((stream->stss_present =
7181           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
7182               &stream->stss) ? TRUE : FALSE) == TRUE) {
7183     /* copy atom data into a new buffer for later use */
7184     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
7185
7186     /* skip version + flags */
7187     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
7188         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
7189       goto corrupt_file;
7190
7191     if (stream->n_sample_syncs) {
7192       /* make sure there's enough data */
7193       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
7194         goto corrupt_file;
7195     }
7196
7197     /* partial sync sample atom */
7198     if ((stream->stps_present =
7199             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
7200                 &stream->stps) ? TRUE : FALSE) == TRUE) {
7201       /* copy atom data into a new buffer for later use */
7202       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
7203
7204       /* skip version + flags */
7205       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
7206           !gst_byte_reader_get_uint32_be (&stream->stps,
7207               &stream->n_sample_partial_syncs))
7208         goto corrupt_file;
7209
7210       /* if there are no entries, the stss table contains the real
7211        * sync samples */
7212       if (stream->n_sample_partial_syncs) {
7213         /* make sure there's enough data */
7214         if (!qt_atom_parser_has_chunks (&stream->stps,
7215                 stream->n_sample_partial_syncs, 4))
7216           goto corrupt_file;
7217       }
7218     }
7219   }
7220
7221   /* sample size */
7222   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
7223     goto no_samples;
7224
7225   /* copy atom data into a new buffer for later use */
7226   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
7227
7228   /* skip version + flags */
7229   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
7230       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
7231     goto corrupt_file;
7232
7233   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
7234     goto corrupt_file;
7235
7236   if (!stream->n_samples)
7237     goto no_samples;
7238
7239   /* sample-to-chunk atom */
7240   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
7241     goto corrupt_file;
7242
7243   /* copy atom data into a new buffer for later use */
7244   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
7245
7246   /* skip version + flags */
7247   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
7248       !gst_byte_reader_get_uint32_be (&stream->stsc,
7249           &stream->n_samples_per_chunk))
7250     goto corrupt_file;
7251
7252   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
7253       stream->n_samples_per_chunk);
7254
7255   /* make sure there's enough data */
7256   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
7257           12))
7258     goto corrupt_file;
7259
7260
7261   /* chunk offset */
7262   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
7263     stream->co_size = sizeof (guint32);
7264   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
7265           &stream->stco))
7266     stream->co_size = sizeof (guint64);
7267   else
7268     goto corrupt_file;
7269
7270   /* copy atom data into a new buffer for later use */
7271   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
7272
7273   /* skip version + flags */
7274   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
7275     goto corrupt_file;
7276
7277   /* chunks_are_samples == TRUE means treat chunks as samples */
7278   stream->chunks_are_samples = stream->sample_size && !stream->sampled;
7279   if (stream->chunks_are_samples) {
7280     /* treat chunks as samples */
7281     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
7282       goto corrupt_file;
7283   } else {
7284     /* skip number of entries */
7285     if (!gst_byte_reader_skip (&stream->stco, 4))
7286       goto corrupt_file;
7287
7288     /* make sure there are enough data in the stsz atom */
7289     if (!stream->sample_size) {
7290       /* different sizes for each sample */
7291       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
7292         goto corrupt_file;
7293     }
7294   }
7295
7296   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
7297       stream->n_samples, (guint) sizeof (QtDemuxSample),
7298       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
7299
7300   if (stream->n_samples >=
7301       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
7302     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
7303         "be larger than %uMB (broken file?)", stream->n_samples,
7304         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
7305     return FALSE;
7306   }
7307
7308   g_assert (stream->samples == NULL);
7309   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
7310   if (!stream->samples) {
7311     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
7312         stream->n_samples);
7313     return FALSE;
7314   }
7315
7316   /* composition time-to-sample */
7317   if ((stream->ctts_present =
7318           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
7319               &stream->ctts) ? TRUE : FALSE) == TRUE) {
7320     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
7321
7322     /* copy atom data into a new buffer for later use */
7323     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
7324
7325     /* skip version + flags */
7326     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
7327         || !gst_byte_reader_get_uint32_be (&stream->ctts,
7328             &stream->n_composition_times))
7329       goto corrupt_file;
7330
7331     /* make sure there's enough data */
7332     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
7333             4 + 4))
7334       goto corrupt_file;
7335
7336     /* This is optional, if missing we iterate the ctts */
7337     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
7338       if (!gst_byte_reader_skip (&cslg, 1 + 3)
7339           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
7340         g_free ((gpointer) cslg.data);
7341         goto corrupt_file;
7342       }
7343     } else {
7344       gint32 cslg_least = 0;
7345       guint num_entries, pos;
7346       gint i;
7347
7348       pos = gst_byte_reader_get_pos (&stream->ctts);
7349       num_entries = stream->n_composition_times;
7350
7351       stream->cslg_shift = 0;
7352
7353       for (i = 0; i < num_entries; i++) {
7354         gint32 offset;
7355
7356         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
7357         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7358
7359         if (offset < cslg_least)
7360           cslg_least = offset;
7361       }
7362
7363       if (cslg_least < 0)
7364         stream->cslg_shift = ABS (cslg_least);
7365       else
7366         stream->cslg_shift = 0;
7367
7368       /* reset the reader so we can generate sample table */
7369       gst_byte_reader_set_pos (&stream->ctts, pos);
7370     }
7371   } else {
7372     /* Ensure the cslg_shift value is consistent so we can use it
7373      * unconditionnally to produce TS and Segment */
7374     stream->cslg_shift = 0;
7375   }
7376
7377   return TRUE;
7378
7379 corrupt_file:
7380   {
7381     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7382         (_("This file is corrupt and cannot be played.")), (NULL));
7383     return FALSE;
7384   }
7385 no_samples:
7386   {
7387     gst_qtdemux_stbl_free (stream);
7388     if (!qtdemux->fragmented) {
7389       /* not quite good */
7390       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
7391       return FALSE;
7392     } else {
7393       /* may pick up samples elsewhere */
7394       return TRUE;
7395     }
7396   }
7397 }
7398
7399 /* collect samples from the next sample to be parsed up to sample @n for @stream
7400  * by reading the info from @stbl
7401  *
7402  * This code can be executed from both the streaming thread and the seeking
7403  * thread so it takes the object lock to protect itself
7404  */
7405 static gboolean
7406 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
7407 {
7408   gint i, j, k;
7409   QtDemuxSample *samples, *first, *cur, *last;
7410   guint32 n_samples_per_chunk;
7411   guint32 n_samples;
7412
7413   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
7414       GST_FOURCC_FORMAT ", pad %s", GST_FOURCC_ARGS (stream->fourcc),
7415       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
7416
7417   n_samples = stream->n_samples;
7418
7419   if (n >= n_samples)
7420     goto out_of_samples;
7421
7422   GST_OBJECT_LOCK (qtdemux);
7423   if (n <= stream->stbl_index)
7424     goto already_parsed;
7425
7426   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
7427
7428   if (!stream->stsz.data) {
7429     /* so we already parsed and passed all the moov samples;
7430      * onto fragmented ones */
7431     g_assert (qtdemux->fragmented);
7432     goto done;
7433   }
7434
7435   /* pointer to the sample table */
7436   samples = stream->samples;
7437
7438   /* starts from -1, moves to the next sample index to parse */
7439   stream->stbl_index++;
7440
7441   /* keep track of the first and last sample to fill */
7442   first = &samples[stream->stbl_index];
7443   last = &samples[n];
7444
7445   if (!stream->chunks_are_samples) {
7446     /* set the sample sizes */
7447     if (stream->sample_size == 0) {
7448       /* different sizes for each sample */
7449       for (cur = first; cur <= last; cur++) {
7450         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
7451         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
7452             (guint) (cur - samples), cur->size);
7453       }
7454     } else {
7455       /* samples have the same size */
7456       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
7457       for (cur = first; cur <= last; cur++)
7458         cur->size = stream->sample_size;
7459     }
7460   }
7461
7462   n_samples_per_chunk = stream->n_samples_per_chunk;
7463   cur = first;
7464
7465   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
7466     guint32 last_chunk;
7467
7468     if (stream->stsc_chunk_index >= stream->last_chunk
7469         || stream->stsc_chunk_index < stream->first_chunk) {
7470       stream->first_chunk =
7471           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7472       stream->samples_per_chunk =
7473           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
7474       gst_byte_reader_skip_unchecked (&stream->stsc, 4);
7475
7476       /* chunk numbers are counted from 1 it seems */
7477       if (G_UNLIKELY (stream->first_chunk == 0))
7478         goto corrupt_file;
7479
7480       --stream->first_chunk;
7481
7482       /* the last chunk of each entry is calculated by taking the first chunk
7483        * of the next entry; except if there is no next, where we fake it with
7484        * INT_MAX */
7485       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
7486         stream->last_chunk = G_MAXUINT32;
7487       } else {
7488         stream->last_chunk =
7489             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
7490         if (G_UNLIKELY (stream->last_chunk == 0))
7491           goto corrupt_file;
7492
7493         --stream->last_chunk;
7494       }
7495
7496       GST_LOG_OBJECT (qtdemux,
7497           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d", i,
7498           stream->first_chunk, stream->last_chunk, stream->samples_per_chunk);
7499
7500       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
7501         goto corrupt_file;
7502
7503       if (stream->last_chunk != G_MAXUINT32) {
7504         if (!qt_atom_parser_peek_sub (&stream->stco,
7505                 stream->first_chunk * stream->co_size,
7506                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
7507                 &stream->co_chunk))
7508           goto corrupt_file;
7509
7510       } else {
7511         stream->co_chunk = stream->stco;
7512         if (!gst_byte_reader_skip (&stream->co_chunk,
7513                 stream->first_chunk * stream->co_size))
7514           goto corrupt_file;
7515       }
7516
7517       stream->stsc_chunk_index = stream->first_chunk;
7518     }
7519
7520     last_chunk = stream->last_chunk;
7521
7522     if (stream->chunks_are_samples) {
7523       cur = &samples[stream->stsc_chunk_index];
7524
7525       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7526         if (j > n) {
7527           /* save state */
7528           stream->stsc_chunk_index = j;
7529           goto done;
7530         }
7531
7532         cur->offset =
7533             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
7534             stream->co_size);
7535
7536         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
7537             "%" G_GUINT64_FORMAT, j, cur->offset);
7538
7539         if (stream->samples_per_frame * stream->bytes_per_frame) {
7540           cur->size =
7541               (stream->samples_per_chunk * stream->n_channels) /
7542               stream->samples_per_frame * stream->bytes_per_frame;
7543         } else {
7544           cur->size = stream->samples_per_chunk;
7545         }
7546
7547         GST_DEBUG_OBJECT (qtdemux,
7548             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
7549             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
7550                     stream->stco_sample_index)), cur->size);
7551
7552         cur->timestamp = stream->stco_sample_index;
7553         cur->duration = stream->samples_per_chunk;
7554         cur->keyframe = TRUE;
7555         cur++;
7556
7557         stream->stco_sample_index += stream->samples_per_chunk;
7558       }
7559       stream->stsc_chunk_index = j;
7560     } else {
7561       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
7562         guint32 samples_per_chunk;
7563         guint64 chunk_offset;
7564
7565         if (!stream->stsc_sample_index
7566             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
7567                 &stream->chunk_offset))
7568           goto corrupt_file;
7569
7570         samples_per_chunk = stream->samples_per_chunk;
7571         chunk_offset = stream->chunk_offset;
7572
7573         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
7574           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
7575               G_GUINT64_FORMAT " and size %d",
7576               (guint) (cur - samples), chunk_offset, cur->size);
7577
7578           cur->offset = chunk_offset;
7579           chunk_offset += cur->size;
7580           cur++;
7581
7582           if (G_UNLIKELY (cur > last)) {
7583             /* save state */
7584             stream->stsc_sample_index = k + 1;
7585             stream->chunk_offset = chunk_offset;
7586             stream->stsc_chunk_index = j;
7587             goto done2;
7588           }
7589         }
7590         stream->stsc_sample_index = 0;
7591       }
7592       stream->stsc_chunk_index = j;
7593     }
7594     stream->stsc_index++;
7595   }
7596
7597   if (stream->chunks_are_samples)
7598     goto ctts;
7599 done2:
7600   {
7601     guint32 n_sample_times;
7602
7603     n_sample_times = stream->n_sample_times;
7604     cur = first;
7605
7606     for (i = stream->stts_index; i < n_sample_times; i++) {
7607       guint32 stts_samples;
7608       gint32 stts_duration;
7609       gint64 stts_time;
7610
7611       if (stream->stts_sample_index >= stream->stts_samples
7612           || !stream->stts_sample_index) {
7613
7614         stream->stts_samples =
7615             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7616         stream->stts_duration =
7617             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
7618
7619         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
7620             i, stream->stts_samples, stream->stts_duration);
7621
7622         stream->stts_sample_index = 0;
7623       }
7624
7625       stts_samples = stream->stts_samples;
7626       stts_duration = stream->stts_duration;
7627       stts_time = stream->stts_time;
7628
7629       for (j = stream->stts_sample_index; j < stts_samples; j++) {
7630         GST_DEBUG_OBJECT (qtdemux,
7631             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
7632             (guint) (cur - samples), j,
7633             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
7634
7635         cur->timestamp = stts_time;
7636         cur->duration = stts_duration;
7637
7638         /* avoid 32-bit wrap-around,
7639          * but still mind possible 'negative' duration */
7640         stts_time += (gint64) stts_duration;
7641         cur++;
7642
7643         if (G_UNLIKELY (cur > last)) {
7644           /* save values */
7645           stream->stts_time = stts_time;
7646           stream->stts_sample_index = j + 1;
7647           goto done3;
7648         }
7649       }
7650       stream->stts_sample_index = 0;
7651       stream->stts_time = stts_time;
7652       stream->stts_index++;
7653     }
7654     /* fill up empty timestamps with the last timestamp, this can happen when
7655      * the last samples do not decode and so we don't have timestamps for them.
7656      * We however look at the last timestamp to estimate the track length so we
7657      * need something in here. */
7658     for (; cur < last; cur++) {
7659       GST_DEBUG_OBJECT (qtdemux,
7660           "fill sample %d: timestamp %" GST_TIME_FORMAT,
7661           (guint) (cur - samples),
7662           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
7663       cur->timestamp = stream->stts_time;
7664       cur->duration = -1;
7665     }
7666   }
7667 done3:
7668   {
7669     /* sample sync, can be NULL */
7670     if (stream->stss_present == TRUE) {
7671       guint32 n_sample_syncs;
7672
7673       n_sample_syncs = stream->n_sample_syncs;
7674
7675       if (!n_sample_syncs) {
7676         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
7677         stream->all_keyframe = TRUE;
7678       } else {
7679         for (i = stream->stss_index; i < n_sample_syncs; i++) {
7680           /* note that the first sample is index 1, not 0 */
7681           guint32 index;
7682
7683           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
7684
7685           if (G_LIKELY (index > 0 && index <= n_samples)) {
7686             index -= 1;
7687             samples[index].keyframe = TRUE;
7688             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7689             /* and exit if we have enough samples */
7690             if (G_UNLIKELY (index >= n)) {
7691               i++;
7692               break;
7693             }
7694           }
7695         }
7696         /* save state */
7697         stream->stss_index = i;
7698       }
7699
7700       /* stps marks partial sync frames like open GOP I-Frames */
7701       if (stream->stps_present == TRUE) {
7702         guint32 n_sample_partial_syncs;
7703
7704         n_sample_partial_syncs = stream->n_sample_partial_syncs;
7705
7706         /* if there are no entries, the stss table contains the real
7707          * sync samples */
7708         if (n_sample_partial_syncs) {
7709           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
7710             /* note that the first sample is index 1, not 0 */
7711             guint32 index;
7712
7713             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
7714
7715             if (G_LIKELY (index > 0 && index <= n_samples)) {
7716               index -= 1;
7717               samples[index].keyframe = TRUE;
7718               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
7719               /* and exit if we have enough samples */
7720               if (G_UNLIKELY (index >= n)) {
7721                 i++;
7722                 break;
7723               }
7724             }
7725           }
7726           /* save state */
7727           stream->stps_index = i;
7728         }
7729       }
7730     } else {
7731       /* no stss, all samples are keyframes */
7732       stream->all_keyframe = TRUE;
7733       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
7734     }
7735   }
7736
7737 ctts:
7738   /* composition time to sample */
7739   if (stream->ctts_present == TRUE) {
7740     guint32 n_composition_times;
7741     guint32 ctts_count;
7742     gint32 ctts_soffset;
7743
7744     /* Fill in the pts_offsets */
7745     cur = first;
7746     n_composition_times = stream->n_composition_times;
7747
7748     for (i = stream->ctts_index; i < n_composition_times; i++) {
7749       if (stream->ctts_sample_index >= stream->ctts_count
7750           || !stream->ctts_sample_index) {
7751         stream->ctts_count =
7752             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
7753         stream->ctts_soffset =
7754             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
7755         stream->ctts_sample_index = 0;
7756       }
7757
7758       ctts_count = stream->ctts_count;
7759       ctts_soffset = stream->ctts_soffset;
7760
7761       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
7762         cur->pts_offset = ctts_soffset;
7763         cur++;
7764
7765         if (G_UNLIKELY (cur > last)) {
7766           /* save state */
7767           stream->ctts_sample_index = j + 1;
7768           goto done;
7769         }
7770       }
7771       stream->ctts_sample_index = 0;
7772       stream->ctts_index++;
7773     }
7774   }
7775 done:
7776   stream->stbl_index = n;
7777   /* if index has been completely parsed, free data that is no-longer needed */
7778   if (n + 1 == stream->n_samples) {
7779     gst_qtdemux_stbl_free (stream);
7780     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
7781     if (qtdemux->pullbased) {
7782       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
7783       while (n + 1 == stream->n_samples)
7784         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
7785           break;
7786     }
7787   }
7788   GST_OBJECT_UNLOCK (qtdemux);
7789
7790   return TRUE;
7791
7792   /* SUCCESS */
7793 already_parsed:
7794   {
7795     GST_LOG_OBJECT (qtdemux,
7796         "Tried to parse up to sample %u but this sample has already been parsed",
7797         n);
7798     /* if fragmented, there may be more */
7799     if (qtdemux->fragmented && n == stream->stbl_index)
7800       goto done;
7801     GST_OBJECT_UNLOCK (qtdemux);
7802     return TRUE;
7803   }
7804   /* ERRORS */
7805 out_of_samples:
7806   {
7807     GST_LOG_OBJECT (qtdemux,
7808         "Tried to parse up to sample %u but there are only %u samples", n + 1,
7809         stream->n_samples);
7810     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7811         (_("This file is corrupt and cannot be played.")), (NULL));
7812     return FALSE;
7813   }
7814 corrupt_file:
7815   {
7816     GST_OBJECT_UNLOCK (qtdemux);
7817     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7818         (_("This file is corrupt and cannot be played.")), (NULL));
7819     return FALSE;
7820   }
7821 }
7822
7823 /* collect all segment info for @stream.
7824  */
7825 static gboolean
7826 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
7827     GNode * trak)
7828 {
7829   GNode *edts;
7830
7831   /* parse and prepare segment info from the edit list */
7832   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
7833   stream->n_segments = 0;
7834   stream->segments = NULL;
7835   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
7836     GNode *elst;
7837     gint n_segments;
7838     gint i, count;
7839     guint64 time;
7840     GstClockTime stime;
7841     guint8 *buffer;
7842
7843     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
7844     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
7845       goto done;
7846
7847     buffer = elst->data;
7848
7849     n_segments = QT_UINT32 (buffer + 12);
7850
7851     /* we might allocate a bit too much, at least allocate 1 segment */
7852     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
7853
7854     /* segments always start from 0 */
7855     time = 0;
7856     stime = 0;
7857     count = 0;
7858     for (i = 0; i < n_segments; i++) {
7859       guint64 duration;
7860       guint64 media_time;
7861       QtDemuxSegment *segment;
7862       guint32 rate_int;
7863 #ifdef TIZEN_FEATURE_GST_UPSTREAM
7864       GstClockTime media_start = GST_CLOCK_TIME_NONE;
7865 #endif
7866
7867       media_time = QT_UINT32 (buffer + 20 + i * 12);
7868       duration = QT_UINT32 (buffer + 16 + i * 12);
7869
7870 #ifdef TIZEN_FEATURE_GST_UPSTREAM
7871       if (media_time != G_MAXUINT32)
7872         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
7873 #endif
7874
7875       segment = &stream->segments[count++];
7876
7877       /* time and duration expressed in global timescale */
7878       segment->time = stime;
7879       /* add non scaled values so we don't cause roundoff errors */
7880 #ifdef TIZEN_FEATURE_GST_UPSTREAM
7881       if (duration || media_start == GST_CLOCK_TIME_NONE) {
7882         time += duration;
7883         stime = QTTIME_TO_GSTTIME (qtdemux, time);
7884         segment->duration = stime - segment->time;
7885       } else {
7886         /* zero duration does not imply media_start == media_stop
7887          * but, only specify media_start.*/
7888         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
7889         if (GST_CLOCK_TIME_IS_VALID (stime) && media_time != G_MAXUINT32
7890             && stime >= media_start) {
7891           segment->duration = stime - media_start;
7892         } else {
7893           segment->duration = GST_CLOCK_TIME_NONE;
7894         }
7895       }
7896 #else
7897       time += duration;
7898       stime = QTTIME_TO_GSTTIME (qtdemux, time);
7899 #endif
7900       segment->stop_time = stime;
7901
7902 #ifndef TIZEN_FEATURE_GST_UPSTREAM
7903       segment->duration = stime - segment->time;
7904 #endif
7905
7906       segment->trak_media_start = media_time;
7907       /* media_time expressed in stream timescale */
7908       if (media_time != G_MAXUINT32) {
7909 #ifdef TIZEN_FEATURE_GST_UPSTREAM
7910         segment->media_start = media_start;
7911 #else
7912         segment->media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
7913 #endif
7914         segment->media_stop = segment->media_start + segment->duration;
7915       } else {
7916         segment->media_start = GST_CLOCK_TIME_NONE;
7917         segment->media_stop = GST_CLOCK_TIME_NONE;
7918       }
7919       rate_int = GST_READ_UINT32_BE (buffer + 24 + i * 12);
7920
7921       if (rate_int <= 1) {
7922         /* 0 is not allowed, some programs write 1 instead of the floating point
7923          * value */
7924         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
7925             rate_int);
7926         segment->rate = 1;
7927       } else {
7928         segment->rate = rate_int / 65536.0;
7929       }
7930
7931       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
7932           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
7933           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
7934           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
7935           i, GST_TIME_ARGS (segment->time),
7936           GST_TIME_ARGS (segment->duration),
7937           GST_TIME_ARGS (segment->media_start), media_time,
7938           GST_TIME_ARGS (segment->media_stop),
7939           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
7940           stream->timescale);
7941       if (segment->stop_time > qtdemux->segment.stop) {
7942         GST_WARNING_OBJECT (qtdemux, "Segment %d "
7943             " extends to %" GST_TIME_FORMAT
7944             " past the end of the file duration %" GST_TIME_FORMAT
7945             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
7946             GST_TIME_ARGS (qtdemux->segment.stop));
7947         qtdemux->segment.stop = segment->stop_time;
7948       }
7949     }
7950     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
7951     stream->n_segments = count;
7952   }
7953 done:
7954
7955   /* push based does not handle segments, so act accordingly here,
7956    * and warn if applicable */
7957   if (!qtdemux->pullbased) {
7958     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
7959     /* remove and use default one below, we stream like it anyway */
7960     g_free (stream->segments);
7961     stream->segments = NULL;
7962     stream->n_segments = 0;
7963   }
7964
7965   /* no segments, create one to play the complete trak */
7966   if (stream->n_segments == 0) {
7967     GstClockTime stream_duration =
7968         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
7969
7970     if (stream->segments == NULL)
7971       stream->segments = g_new (QtDemuxSegment, 1);
7972
7973     /* represent unknown our way */
7974     if (stream_duration == 0)
7975       stream_duration = GST_CLOCK_TIME_NONE;
7976
7977     stream->segments[0].time = 0;
7978     stream->segments[0].stop_time = stream_duration;
7979     stream->segments[0].duration = stream_duration;
7980     stream->segments[0].media_start = 0;
7981     stream->segments[0].media_stop = stream_duration;
7982     stream->segments[0].rate = 1.0;
7983     stream->segments[0].trak_media_start = 0;
7984
7985     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
7986         GST_TIME_ARGS (stream_duration));
7987     stream->n_segments = 1;
7988     stream->dummy_segment = TRUE;
7989   }
7990   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
7991
7992   return TRUE;
7993 }
7994
7995 /*
7996  * Parses the stsd atom of a svq3 trak looking for
7997  * the SMI and gama atoms.
7998  */
7999 static void
8000 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
8001     guint8 ** gamma, GstBuffer ** seqh)
8002 {
8003   guint8 *_gamma = NULL;
8004   GstBuffer *_seqh = NULL;
8005   guint8 *stsd_data = stsd->data;
8006   guint32 length = QT_UINT32 (stsd_data);
8007   guint16 version;
8008
8009   if (length < 32) {
8010     GST_WARNING_OBJECT (qtdemux, "stsd too short");
8011     goto end;
8012   }
8013
8014   stsd_data += 32;
8015   length -= 32;
8016   version = QT_UINT16 (stsd_data);
8017   if (version == 3) {
8018     if (length >= 70) {
8019       length -= 70;
8020       stsd_data += 70;
8021       while (length > 8) {
8022         guint32 fourcc, size;
8023         guint8 *data;
8024         size = QT_UINT32 (stsd_data);
8025         fourcc = QT_FOURCC (stsd_data + 4);
8026         data = stsd_data + 8;
8027
8028         if (size == 0) {
8029           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
8030               "svq3 atom parsing");
8031           goto end;
8032         }
8033
8034         switch (fourcc) {
8035           case FOURCC_gama:{
8036             if (size == 12) {
8037               _gamma = data;
8038             } else {
8039               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
8040                   " for gama atom, expected 12", size);
8041             }
8042             break;
8043           }
8044           case FOURCC_SMI_:{
8045             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
8046               guint32 seqh_size;
8047               if (_seqh != NULL) {
8048                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
8049                     " found, ignoring");
8050               } else {
8051                 seqh_size = QT_UINT32 (data + 4);
8052                 if (seqh_size > 0) {
8053                   _seqh = gst_buffer_new_and_alloc (seqh_size);
8054                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
8055                 }
8056               }
8057             }
8058             break;
8059           }
8060           default:{
8061             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
8062                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
8063           }
8064         }
8065
8066         if (size <= length) {
8067           length -= size;
8068           stsd_data += size;
8069         }
8070       }
8071     } else {
8072       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
8073     }
8074   } else {
8075     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
8076         G_GUINT16_FORMAT, version);
8077     goto end;
8078   }
8079
8080 end:
8081   if (gamma) {
8082     *gamma = _gamma;
8083   }
8084   if (seqh) {
8085     *seqh = _seqh;
8086   } else if (_seqh) {
8087     gst_buffer_unref (_seqh);
8088   }
8089 }
8090
8091 static gchar *
8092 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
8093 {
8094   GNode *dinf;
8095   GstByteReader dref;
8096   gchar *uri = NULL;
8097
8098   /*
8099    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
8100    * atom that might contain a 'data' atom with the rtsp uri.
8101    * This case was reported in bug #597497, some info about
8102    * the hndl atom can be found in TN1195
8103    */
8104   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
8105   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
8106
8107   if (dinf) {
8108     guint32 dref_num_entries = 0;
8109     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
8110         gst_byte_reader_skip (&dref, 4) &&
8111         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
8112       gint i;
8113
8114       /* search dref entries for hndl atom */
8115       for (i = 0; i < dref_num_entries; i++) {
8116         guint32 size = 0, type;
8117         guint8 string_len = 0;
8118         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
8119             qt_atom_parser_get_fourcc (&dref, &type)) {
8120           if (type == FOURCC_hndl) {
8121             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
8122
8123             /* skip data reference handle bytes and the
8124              * following pascal string and some extra 4
8125              * bytes I have no idea what are */
8126             if (!gst_byte_reader_skip (&dref, 4) ||
8127                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
8128                 !gst_byte_reader_skip (&dref, string_len + 4)) {
8129               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
8130               break;
8131             }
8132
8133             /* iterate over the atoms to find the data atom */
8134             while (gst_byte_reader_get_remaining (&dref) >= 8) {
8135               guint32 atom_size;
8136               guint32 atom_type;
8137
8138               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
8139                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
8140                 if (atom_type == FOURCC_data) {
8141                   const guint8 *uri_aux = NULL;
8142
8143                   /* found the data atom that might contain the rtsp uri */
8144                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
8145                       "hndl atom, interpreting it as an URI");
8146                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
8147                           &uri_aux)) {
8148                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
8149                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
8150                     else
8151                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
8152                           "didn't contain a rtsp address");
8153                   } else {
8154                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
8155                         "atom contents");
8156                   }
8157                   break;
8158                 }
8159                 /* skipping to the next entry */
8160                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
8161                   break;
8162               } else {
8163                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
8164                     "atom header");
8165                 break;
8166               }
8167             }
8168             break;
8169           }
8170           /* skip to the next entry */
8171           if (!gst_byte_reader_skip (&dref, size - 8))
8172             break;
8173         } else {
8174           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
8175         }
8176       }
8177       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
8178     }
8179   }
8180   return uri;
8181 }
8182
8183 #define AMR_NB_ALL_MODES        0x81ff
8184 #define AMR_WB_ALL_MODES        0x83ff
8185 static guint
8186 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
8187 {
8188   /* The 'damr' atom is of the form:
8189    *
8190    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
8191    *    32 b       8 b          16 b           8 b                 8 b
8192    *
8193    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
8194    * represents the highest mode used in the stream (and thus the maximum
8195    * bitrate), with a couple of special cases as seen below.
8196    */
8197
8198   /* Map of frame type ID -> bitrate */
8199   static const guint nb_bitrates[] = {
8200     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
8201   };
8202   static const guint wb_bitrates[] = {
8203     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
8204   };
8205   GstMapInfo map;
8206   gsize max_mode;
8207   guint16 mode_set;
8208
8209   gst_buffer_map (buf, &map, GST_MAP_READ);
8210
8211   if (map.size != 0x11) {
8212     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
8213     goto bad_data;
8214   }
8215
8216   if (QT_FOURCC (map.data + 4) != GST_MAKE_FOURCC ('d', 'a', 'm', 'r')) {
8217     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
8218         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
8219     goto bad_data;
8220   }
8221
8222   mode_set = QT_UINT16 (map.data + 13);
8223
8224   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
8225     max_mode = 7 + (wb ? 1 : 0);
8226   else
8227     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
8228     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
8229
8230   if (max_mode == -1) {
8231     GST_DEBUG ("No mode indication was found (mode set) = %x",
8232         (guint) mode_set);
8233     goto bad_data;
8234   }
8235
8236   gst_buffer_unmap (buf, &map);
8237   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
8238
8239 bad_data:
8240   gst_buffer_unmap (buf, &map);
8241   return 0;
8242 }
8243
8244 static gboolean
8245 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
8246     GstByteReader * reader, guint32 * matrix, const gchar * atom)
8247 {
8248   /*
8249    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
8250    * [0 1 2]
8251    * [3 4 5]
8252    * [6 7 8]
8253    */
8254
8255   if (gst_byte_reader_get_remaining (reader) < 36)
8256     return FALSE;
8257
8258   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
8259   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
8260   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
8261   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
8262   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
8263   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
8264   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
8265   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
8266   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
8267
8268   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
8269   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
8270       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
8271       matrix[2] & 0xFF);
8272   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
8273       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
8274       matrix[5] & 0xFF);
8275   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
8276       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
8277       matrix[8] & 0xFF);
8278
8279   return TRUE;
8280 }
8281
8282 static void
8283 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
8284     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
8285 {
8286
8287 /* [a b c]
8288  * [d e f]
8289  * [g h i]
8290  *
8291  * This macro will only compare value abdegh, it expects cfi to have already
8292  * been checked
8293  */
8294 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
8295                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
8296
8297   /* only handle the cases where the last column has standard values */
8298   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
8299     const gchar *rotation_tag = NULL;
8300
8301     /* no rotation needed */
8302     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
8303       /* NOP */
8304     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
8305       rotation_tag = "rotate-90";
8306     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
8307       rotation_tag = "rotate-180";
8308     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
8309       rotation_tag = "rotate-270";
8310     } else {
8311       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8312     }
8313
8314     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
8315         rotation_tag);
8316     if (rotation_tag != NULL) {
8317       if (*taglist == NULL)
8318         *taglist = gst_tag_list_new_empty ();
8319       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
8320           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
8321     }
8322   } else {
8323     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
8324   }
8325 }
8326
8327 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
8328  * protected streams (sinf, frma, schm and schi); if the protection scheme is
8329  * Common Encryption (cenc), the function will also parse the tenc box (defined
8330  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
8331  * (typically an enc[v|a|t|s] sample entry); the function will set
8332  * @original_fmt to the fourcc of the original unencrypted stream format.
8333  * Returns TRUE if successful; FALSE otherwise. */
8334 static gboolean
8335 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
8336     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
8337 {
8338   GNode *sinf;
8339   GNode *frma;
8340   GNode *schm;
8341   GNode *schi;
8342
8343   g_return_val_if_fail (qtdemux != NULL, FALSE);
8344   g_return_val_if_fail (stream != NULL, FALSE);
8345   g_return_val_if_fail (container != NULL, FALSE);
8346   g_return_val_if_fail (original_fmt != NULL, FALSE);
8347
8348   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
8349   if (G_UNLIKELY (!sinf)) {
8350     if (stream->protection_scheme_type == FOURCC_cenc) {
8351       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
8352           "mandatory for Common Encryption");
8353       return FALSE;
8354     }
8355     return TRUE;
8356   }
8357
8358   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
8359   if (G_UNLIKELY (!frma)) {
8360     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
8361     return FALSE;
8362   }
8363
8364   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
8365   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
8366       GST_FOURCC_ARGS (*original_fmt));
8367
8368   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
8369   if (!schm) {
8370     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
8371     return FALSE;
8372   }
8373   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
8374   stream->protection_scheme_version =
8375       QT_UINT32 ((const guint8 *) schm->data + 16);
8376
8377   GST_DEBUG_OBJECT (qtdemux,
8378       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
8379       "protection_scheme_version: %#010x",
8380       GST_FOURCC_ARGS (stream->protection_scheme_type),
8381       stream->protection_scheme_version);
8382
8383   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
8384   if (!schi) {
8385     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
8386     return FALSE;
8387   }
8388   if (stream->protection_scheme_type == FOURCC_cenc) {
8389     QtDemuxCencSampleSetInfo *info;
8390     GNode *tenc;
8391     const guint8 *tenc_data;
8392     guint32 isEncrypted;
8393     guint8 iv_size;
8394     const guint8 *default_kid;
8395     GstBuffer *kid_buf;
8396
8397     if (G_UNLIKELY (!stream->protection_scheme_info))
8398       stream->protection_scheme_info =
8399           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
8400
8401     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
8402
8403     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
8404     if (!tenc) {
8405       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
8406           "which is mandatory for Common Encryption");
8407       return FALSE;
8408     }
8409     tenc_data = (const guint8 *) tenc->data + 12;
8410     isEncrypted = QT_UINT24 (tenc_data);
8411     iv_size = QT_UINT8 (tenc_data + 3);
8412     default_kid = (tenc_data + 4);
8413     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
8414     gst_buffer_fill (kid_buf, 0, default_kid, 16);
8415     if (info->default_properties)
8416       gst_structure_free (info->default_properties);
8417     info->default_properties =
8418         gst_structure_new ("application/x-cenc",
8419         "iv_size", G_TYPE_UINT, iv_size,
8420         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
8421         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
8422     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
8423         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
8424     gst_buffer_unref (kid_buf);
8425   }
8426   return TRUE;
8427 }
8428
8429 /* parse the traks.
8430  * With each track we associate a new QtDemuxStream that contains all the info
8431  * about the trak.
8432  * traks that do not decode to something (like strm traks) will not have a pad.
8433  */
8434 static gboolean
8435 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
8436 {
8437   GstByteReader tkhd;
8438   int offset;
8439   GNode *mdia;
8440   GNode *mdhd;
8441   GNode *hdlr;
8442   GNode *minf;
8443   GNode *stbl;
8444   GNode *stsd;
8445   GNode *mp4a;
8446   GNode *mp4v;
8447   GNode *wave;
8448   GNode *esds;
8449   GNode *pasp;
8450   GNode *tref;
8451   GNode *udta;
8452   GNode *svmi;
8453
8454   QtDemuxStream *stream = NULL;
8455   gboolean new_stream = FALSE;
8456   gchar *codec = NULL;
8457   const guint8 *stsd_data;
8458   guint16 lang_code;            /* quicktime lang code or packed iso code */
8459   guint32 version;
8460   guint32 tkhd_flags = 0;
8461   guint8 tkhd_version = 0;
8462   guint32 fourcc;
8463   guint value_size, stsd_len, len;
8464   guint32 track_id;
8465
8466   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
8467
8468   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
8469       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
8470       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
8471     goto corrupt_file;
8472
8473   /* pick between 64 or 32 bits */
8474   value_size = tkhd_version == 1 ? 8 : 4;
8475   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
8476       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
8477     goto corrupt_file;
8478
8479   if (!qtdemux->got_moov) {
8480     if (qtdemux_find_stream (qtdemux, track_id))
8481       goto existing_stream;
8482     stream = _create_stream ();
8483     stream->track_id = track_id;
8484     new_stream = TRUE;
8485   } else {
8486     stream = qtdemux_find_stream (qtdemux, track_id);
8487     if (!stream) {
8488       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
8489       goto skip_track;
8490     }
8491
8492     /* flush samples data from this track from previous moov */
8493     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
8494     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
8495   }
8496
8497   if (stream->pending_tags == NULL)
8498     stream->pending_tags = gst_tag_list_new_empty ();
8499
8500   if ((tkhd_flags & 1) == 0)
8501     stream->disabled = TRUE;
8502
8503   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
8504       tkhd_version, tkhd_flags, stream->track_id);
8505
8506   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
8507     goto corrupt_file;
8508
8509   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
8510     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
8511     if (qtdemux->major_brand != FOURCC_mjp2 ||
8512         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
8513       goto corrupt_file;
8514   }
8515
8516   len = QT_UINT32 ((guint8 *) mdhd->data);
8517   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
8518   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
8519   if (version == 0x01000000) {
8520     if (len < 38)
8521       goto corrupt_file;
8522     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
8523     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
8524     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
8525   } else {
8526     if (len < 30)
8527       goto corrupt_file;
8528     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
8529     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
8530     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
8531   }
8532
8533   if (lang_code < 0x400) {
8534     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
8535   } else if (lang_code == 0x7fff) {
8536     stream->lang_id[0] = 0;     /* unspecified */
8537   } else {
8538     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
8539     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
8540     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
8541     stream->lang_id[3] = 0;
8542   }
8543
8544   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
8545       stream->timescale);
8546   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
8547       stream->duration);
8548   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
8549       lang_code, stream->lang_id);
8550
8551   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
8552     goto corrupt_file;
8553
8554   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
8555     /* chapters track reference */
8556     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
8557     if (chap) {
8558       gsize length = GST_READ_UINT32_BE (chap->data);
8559       if (qtdemux->chapters_track_id)
8560         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
8561
8562       if (length >= 12) {
8563         qtdemux->chapters_track_id =
8564             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
8565       }
8566     }
8567   }
8568
8569   /* fragmented files may have bogus duration in moov */
8570   if (!qtdemux->fragmented &&
8571       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
8572     guint64 tdur1, tdur2;
8573
8574     /* don't overflow */
8575     tdur1 = stream->timescale * (guint64) qtdemux->duration;
8576     tdur2 = qtdemux->timescale * (guint64) stream->duration;
8577
8578     /* HACK:
8579      * some of those trailers, nowadays, have prologue images that are
8580      * themselves vide tracks as well. I haven't really found a way to
8581      * identify those yet, except for just looking at their duration. */
8582     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
8583       GST_WARNING_OBJECT (qtdemux,
8584           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
8585           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
8586           "found, assuming preview image or something; skipping track",
8587           stream->duration, stream->timescale, qtdemux->duration,
8588           qtdemux->timescale);
8589       if (new_stream)
8590         gst_qtdemux_stream_free (qtdemux, stream);
8591       return TRUE;
8592     }
8593   }
8594
8595   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
8596     goto corrupt_file;
8597
8598   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
8599       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
8600
8601   len = QT_UINT32 ((guint8 *) hdlr->data);
8602   if (len >= 20)
8603     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
8604   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
8605       GST_FOURCC_ARGS (stream->subtype));
8606
8607   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
8608     goto corrupt_file;
8609
8610   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
8611     goto corrupt_file;
8612
8613   /*parse svmi header if existing */
8614   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
8615   if (svmi) {
8616     len = QT_UINT32 ((guint8 *) svmi->data);
8617     version = QT_UINT32 ((guint8 *) svmi->data + 8);
8618     if (!version) {
8619       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
8620       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
8621       guint8 frame_type, frame_layout;
8622
8623       /* MPEG-A stereo video */
8624       if (qtdemux->major_brand == FOURCC_ss02)
8625         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
8626
8627       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
8628       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
8629       switch (frame_type) {
8630         case 0:
8631           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
8632           break;
8633         case 1:
8634           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
8635           break;
8636         case 2:
8637           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
8638           break;
8639         case 3:
8640           /* mode 3 is primary/secondary view sequence, ie
8641            * left/right views in separate tracks. See section 7.2
8642            * of ISO/IEC 23000-11:2009 */
8643           GST_FIXME_OBJECT (qtdemux,
8644               "Implement stereo video in separate streams");
8645       }
8646
8647       if ((frame_layout & 0x1) == 0)
8648         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
8649
8650       GST_LOG_OBJECT (qtdemux,
8651           "StereoVideo: composition type: %u, is_left_first: %u",
8652           frame_type, frame_layout);
8653       stream->multiview_mode = mode;
8654       stream->multiview_flags = flags;
8655     }
8656   }
8657
8658   /* parse stsd */
8659   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
8660     goto corrupt_file;
8661   stsd_data = (const guint8 *) stsd->data;
8662
8663   /* stsd should at least have one entry */
8664   stsd_len = QT_UINT32 (stsd_data);
8665   if (stsd_len < 24) {
8666     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
8667     if (stream->subtype == FOURCC_vivo) {
8668       if (new_stream)
8669         gst_qtdemux_stream_free (qtdemux, stream);
8670       return TRUE;
8671     } else {
8672       goto corrupt_file;
8673     }
8674   }
8675
8676   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
8677
8678   /* and that entry should fit within stsd */
8679   len = QT_UINT32 (stsd_data + 16);
8680   if (len > stsd_len + 16)
8681     goto corrupt_file;
8682
8683   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
8684   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
8685       GST_FOURCC_ARGS (stream->fourcc));
8686   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
8687
8688   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
8689     goto error_encrypted;
8690
8691   if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
8692     GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
8693     stream->protected = TRUE;
8694     if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
8695       GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
8696   }
8697
8698   if (stream->subtype == FOURCC_vide) {
8699     guint32 w = 0, h = 0;
8700     gboolean gray;
8701     gint depth, palette_size, palette_count;
8702     guint32 matrix[9];
8703     guint32 *palette_data = NULL;
8704
8705     stream->sampled = TRUE;
8706
8707     /* version 1 uses some 64-bit ints */
8708     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
8709       goto corrupt_file;
8710
8711     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
8712       goto corrupt_file;
8713
8714     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
8715         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
8716       goto corrupt_file;
8717
8718     stream->display_width = w >> 16;
8719     stream->display_height = h >> 16;
8720
8721     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
8722         &stream->pending_tags);
8723
8724     offset = 16;
8725     if (len < 86)
8726       goto corrupt_file;
8727
8728     stream->width = QT_UINT16 (stsd_data + offset + 32);
8729     stream->height = QT_UINT16 (stsd_data + offset + 34);
8730     stream->fps_n = 0;          /* this is filled in later */
8731     stream->fps_d = 0;          /* this is filled in later */
8732     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
8733     stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
8734
8735     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
8736         stream->width, stream->height, stream->bits_per_sample,
8737         stream->color_table_id);
8738
8739     depth = stream->bits_per_sample;
8740
8741     /* more than 32 bits means grayscale */
8742     gray = (depth > 32);
8743     /* low 32 bits specify the depth  */
8744     depth &= 0x1F;
8745
8746     /* different number of palette entries is determined by depth. */
8747     palette_count = 0;
8748     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
8749       palette_count = (1 << depth);
8750     palette_size = palette_count * 4;
8751
8752     if (stream->color_table_id) {
8753       switch (palette_count) {
8754         case 0:
8755           break;
8756         case 2:
8757           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
8758           break;
8759         case 4:
8760           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
8761           break;
8762         case 16:
8763           if (gray)
8764             palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
8765           else
8766             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
8767           break;
8768         case 256:
8769           if (gray)
8770             palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
8771           else
8772             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
8773           break;
8774         default:
8775           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
8776               (_("The video in this file might not play correctly.")),
8777               ("unsupported palette depth %d", depth));
8778           break;
8779       }
8780     } else {
8781       gint i, j, start, end;
8782
8783       if (len < 94)
8784         goto corrupt_file;
8785
8786       /* read table */
8787       start = QT_UINT32 (stsd_data + offset + 86);
8788       palette_count = QT_UINT16 (stsd_data + offset + 90);
8789       end = QT_UINT16 (stsd_data + offset + 92);
8790
8791       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
8792           start, end, palette_count);
8793
8794       if (end > 255)
8795         end = 255;
8796       if (start > end)
8797         start = end;
8798
8799       if (len < 94 + (end - start) * 8)
8800         goto corrupt_file;
8801
8802       /* palette is always the same size */
8803       palette_data = g_malloc0 (256 * 4);
8804       palette_size = 256 * 4;
8805
8806       for (j = 0, i = start; i <= end; j++, i++) {
8807         guint32 a, r, g, b;
8808
8809         a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
8810         r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
8811         g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
8812         b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
8813
8814         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
8815             (g & 0xff00) | (b >> 8);
8816       }
8817     }
8818
8819     if (stream->caps)
8820       gst_caps_unref (stream->caps);
8821
8822     stream->caps =
8823         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
8824     if (G_UNLIKELY (!stream->caps)) {
8825       g_free (palette_data);
8826       goto unknown_stream;
8827     }
8828
8829     if (codec) {
8830       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8831           GST_TAG_VIDEO_CODEC, codec, NULL);
8832       g_free (codec);
8833       codec = NULL;
8834     }
8835
8836
8837     if (palette_data) {
8838       GstStructure *s;
8839
8840       if (stream->rgb8_palette)
8841         gst_memory_unref (stream->rgb8_palette);
8842       stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
8843           palette_data, palette_size, 0, palette_size, palette_data, g_free);
8844
8845       s = gst_caps_get_structure (stream->caps, 0);
8846
8847       /* non-raw video has a palette_data property. raw video has the palette as
8848        * an extra plane that we append to the output buffers before we push
8849        * them*/
8850       if (!gst_structure_has_name (s, "video/x-raw")) {
8851         GstBuffer *palette;
8852
8853         palette = gst_buffer_new ();
8854         gst_buffer_append_memory (palette, stream->rgb8_palette);
8855         stream->rgb8_palette = NULL;
8856
8857         gst_caps_set_simple (stream->caps, "palette_data",
8858             GST_TYPE_BUFFER, palette, NULL);
8859         gst_buffer_unref (palette);
8860       }
8861     } else if (palette_count != 0) {
8862       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
8863           (NULL), ("Unsupported palette depth %d", depth));
8864     }
8865
8866     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
8867         QT_UINT16 (stsd_data + offset + 48));
8868
8869     esds = NULL;
8870     pasp = NULL;
8871     /* pick 'the' stsd child */
8872     if (!stream->protected)
8873       mp4v = qtdemux_tree_get_child_by_type (stsd, fourcc);
8874     else
8875       mp4v = qtdemux_tree_get_child_by_type (stsd, FOURCC_encv);
8876
8877     if (mp4v) {
8878       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
8879       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
8880     }
8881
8882     if (pasp) {
8883       const guint8 *pasp_data = (const guint8 *) pasp->data;
8884
8885       stream->par_w = QT_UINT32 (pasp_data + 8);
8886       stream->par_h = QT_UINT32 (pasp_data + 12);
8887     } else {
8888       stream->par_w = 0;
8889       stream->par_h = 0;
8890     }
8891
8892     if (esds) {
8893       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
8894     } else {
8895       switch (fourcc) {
8896         case FOURCC_H264:
8897         case FOURCC_avc1:
8898         case FOURCC_avc3:
8899         {
8900           gint len = QT_UINT32 (stsd_data) - 0x66;
8901           const guint8 *avc_data = stsd_data + 0x66;
8902
8903           /* find avcC */
8904           while (len >= 0x8) {
8905             gint size;
8906
8907             if (QT_UINT32 (avc_data) <= len)
8908               size = QT_UINT32 (avc_data) - 0x8;
8909             else
8910               size = len - 0x8;
8911
8912             if (size < 1)
8913               /* No real data, so break out */
8914               break;
8915
8916             switch (QT_FOURCC (avc_data + 0x4)) {
8917               case FOURCC_avcC:
8918               {
8919                 /* parse, if found */
8920                 GstBuffer *buf;
8921
8922                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
8923
8924                 /* First 4 bytes are the length of the atom, the next 4 bytes
8925                  * are the fourcc, the next 1 byte is the version, and the
8926                  * subsequent bytes are profile_tier_level structure like data. */
8927                 gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
8928                     avc_data + 8 + 1, size - 1);
8929                 buf = gst_buffer_new_and_alloc (size);
8930                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
8931                 gst_caps_set_simple (stream->caps,
8932                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
8933                 gst_buffer_unref (buf);
8934
8935                 break;
8936               }
8937               case FOURCC_strf:
8938               {
8939                 GstBuffer *buf;
8940
8941                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
8942
8943                 /* First 4 bytes are the length of the atom, the next 4 bytes
8944                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
8945                  * next 1 byte is the version, and the
8946                  * subsequent bytes are sequence parameter set like data. */
8947
8948                 size -= 40;     /* we'll be skipping BITMAPINFOHEADER */
8949                 if (size > 1) {
8950                   gst_codec_utils_h264_caps_set_level_and_profile (stream->caps,
8951                       avc_data + 8 + 40 + 1, size - 1);
8952
8953                   buf = gst_buffer_new_and_alloc (size);
8954                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
8955                   gst_caps_set_simple (stream->caps,
8956                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
8957                   gst_buffer_unref (buf);
8958                 }
8959                 break;
8960               }
8961               case FOURCC_btrt:
8962               {
8963                 guint avg_bitrate, max_bitrate;
8964
8965                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
8966                 if (size < 12)
8967                   break;
8968
8969                 max_bitrate = QT_UINT32 (avc_data + 0xc);
8970                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
8971
8972                 if (!max_bitrate && !avg_bitrate)
8973                   break;
8974
8975                 /* Some muxers seem to swap the average and maximum bitrates
8976                  * (I'm looking at you, YouTube), so we swap for sanity. */
8977                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
8978                   guint temp = avg_bitrate;
8979
8980                   avg_bitrate = max_bitrate;
8981                   max_bitrate = temp;
8982                 }
8983
8984                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
8985                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8986                       GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
8987                 }
8988                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
8989                   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
8990                       GST_TAG_BITRATE, avg_bitrate, NULL);
8991                 }
8992
8993                 break;
8994               }
8995
8996               default:
8997                 break;
8998             }
8999
9000             len -= size + 8;
9001             avc_data += size + 8;
9002           }
9003
9004           break;
9005         }
9006         case FOURCC_H265:
9007         case FOURCC_hvc1:
9008         case FOURCC_hev1:
9009         {
9010           gint len = QT_UINT32 (stsd_data) - 0x66;
9011           const guint8 *hevc_data = stsd_data + 0x66;
9012
9013           /* find hevc */
9014           while (len >= 0x8) {
9015             gint size;
9016
9017             if (QT_UINT32 (hevc_data) <= len)
9018               size = QT_UINT32 (hevc_data) - 0x8;
9019             else
9020               size = len - 0x8;
9021
9022             if (size < 1)
9023               /* No real data, so break out */
9024               break;
9025
9026             switch (QT_FOURCC (hevc_data + 0x4)) {
9027               case FOURCC_hvcC:
9028               {
9029                 /* parse, if found */
9030                 GstBuffer *buf;
9031
9032                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
9033
9034                 /* First 4 bytes are the length of the atom, the next 4 bytes
9035                  * are the fourcc, the next 1 byte is the version, and the
9036                  * subsequent bytes are sequence parameter set like data. */
9037                 gst_codec_utils_h265_caps_set_level_tier_and_profile
9038                     (stream->caps, hevc_data + 8 + 1, size - 1);
9039
9040                 buf = gst_buffer_new_and_alloc (size);
9041                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
9042                 gst_caps_set_simple (stream->caps,
9043                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9044                 gst_buffer_unref (buf);
9045                 break;
9046               }
9047               default:
9048                 break;
9049             }
9050             len -= size + 8;
9051             hevc_data += size + 8;
9052           }
9053           break;
9054         }
9055         case FOURCC_mp4v:
9056         case FOURCC_MP4V:
9057         case FOURCC_fmp4:
9058         case FOURCC_FMP4:
9059         {
9060           GNode *glbl;
9061
9062           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
9063               GST_FOURCC_ARGS (fourcc));
9064
9065           /* codec data might be in glbl extension atom */
9066           glbl = mp4v ?
9067               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
9068           if (glbl) {
9069             guint8 *data;
9070             GstBuffer *buf;
9071             gint len;
9072
9073             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
9074             data = glbl->data;
9075             len = QT_UINT32 (data);
9076             if (len > 0x8) {
9077               len -= 0x8;
9078               buf = gst_buffer_new_and_alloc (len);
9079               gst_buffer_fill (buf, 0, data + 8, len);
9080               gst_caps_set_simple (stream->caps,
9081                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9082               gst_buffer_unref (buf);
9083             }
9084           }
9085           break;
9086         }
9087         case FOURCC_mjp2:
9088         {
9089           /* see annex I of the jpeg2000 spec */
9090           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
9091           const guint8 *data;
9092           const gchar *colorspace = NULL;
9093           gint ncomp = 0;
9094           guint32 ncomp_map = 0;
9095           gint32 *comp_map = NULL;
9096           guint32 nchan_def = 0;
9097           gint32 *chan_def = NULL;
9098
9099           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
9100           /* some required atoms */
9101           mjp2 = qtdemux_tree_get_child_by_type (stsd, FOURCC_mjp2);
9102           if (!mjp2)
9103             break;
9104           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
9105           if (!jp2h)
9106             break;
9107
9108           /* number of components; redundant with info in codestream, but useful
9109              to a muxer */
9110           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
9111           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
9112             break;
9113           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
9114
9115           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
9116           if (!colr)
9117             break;
9118           GST_DEBUG_OBJECT (qtdemux, "found colr");
9119           /* extract colour space info */
9120           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
9121             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
9122               case 16:
9123                 colorspace = "sRGB";
9124                 break;
9125               case 17:
9126                 colorspace = "GRAY";
9127                 break;
9128               case 18:
9129                 colorspace = "sYUV";
9130                 break;
9131               default:
9132                 colorspace = NULL;
9133                 break;
9134             }
9135           }
9136           if (!colorspace)
9137             /* colr is required, and only values 16, 17, and 18 are specified,
9138                so error if we have no colorspace */
9139             break;
9140
9141           /* extract component mapping */
9142           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
9143           if (cmap) {
9144             guint32 cmap_len = 0;
9145             int i;
9146             cmap_len = QT_UINT32 (cmap->data);
9147             if (cmap_len >= 8) {
9148               /* normal box, subtract off header */
9149               cmap_len -= 8;
9150               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
9151               if (cmap_len % 4 == 0) {
9152                 ncomp_map = (cmap_len / 4);
9153                 comp_map = g_new0 (gint32, ncomp_map);
9154                 for (i = 0; i < ncomp_map; i++) {
9155                   guint16 cmp;
9156                   guint8 mtyp, pcol;
9157                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
9158                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
9159                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
9160                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
9161                 }
9162               }
9163             }
9164           }
9165           /* extract channel definitions */
9166           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
9167           if (cdef) {
9168             guint32 cdef_len = 0;
9169             int i;
9170             cdef_len = QT_UINT32 (cdef->data);
9171             if (cdef_len >= 10) {
9172               /* normal box, subtract off header and len */
9173               cdef_len -= 10;
9174               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
9175               if (cdef_len % 6 == 0) {
9176                 nchan_def = (cdef_len / 6);
9177                 chan_def = g_new0 (gint32, nchan_def);
9178                 for (i = 0; i < nchan_def; i++)
9179                   chan_def[i] = -1;
9180                 for (i = 0; i < nchan_def; i++) {
9181                   guint16 cn, typ, asoc;
9182                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
9183                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
9184                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
9185                   if (cn < nchan_def) {
9186                     switch (typ) {
9187                       case 0:
9188                         chan_def[cn] = asoc;
9189                         break;
9190                       case 1:
9191                         chan_def[cn] = 0;       /* alpha */
9192                         break;
9193                       default:
9194                         chan_def[cn] = -typ;
9195                     }
9196                   }
9197                 }
9198               }
9199             }
9200           }
9201
9202           gst_caps_set_simple (stream->caps,
9203               "num-components", G_TYPE_INT, ncomp, NULL);
9204           gst_caps_set_simple (stream->caps,
9205               "colorspace", G_TYPE_STRING, colorspace, NULL);
9206
9207           if (comp_map) {
9208             GValue arr = { 0, };
9209             GValue elt = { 0, };
9210             int i;
9211             g_value_init (&arr, GST_TYPE_ARRAY);
9212             g_value_init (&elt, G_TYPE_INT);
9213             for (i = 0; i < ncomp_map; i++) {
9214               g_value_set_int (&elt, comp_map[i]);
9215               gst_value_array_append_value (&arr, &elt);
9216             }
9217             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9218                 "component-map", &arr);
9219             g_value_unset (&elt);
9220             g_value_unset (&arr);
9221             g_free (comp_map);
9222           }
9223
9224           if (chan_def) {
9225             GValue arr = { 0, };
9226             GValue elt = { 0, };
9227             int i;
9228             g_value_init (&arr, GST_TYPE_ARRAY);
9229             g_value_init (&elt, G_TYPE_INT);
9230             for (i = 0; i < nchan_def; i++) {
9231               g_value_set_int (&elt, chan_def[i]);
9232               gst_value_array_append_value (&arr, &elt);
9233             }
9234             gst_structure_set_value (gst_caps_get_structure (stream->caps, 0),
9235                 "channel-definitions", &arr);
9236             g_value_unset (&elt);
9237             g_value_unset (&arr);
9238             g_free (chan_def);
9239           }
9240
9241           /* some optional atoms */
9242           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
9243           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
9244
9245           /* indicate possible fields in caps */
9246           if (field) {
9247             data = (guint8 *) field->data + 8;
9248             if (*data != 1)
9249               gst_caps_set_simple (stream->caps, "fields", G_TYPE_INT,
9250                   (gint) * data, NULL);
9251           }
9252           /* add codec_data if provided */
9253           if (prefix) {
9254             GstBuffer *buf;
9255             gint len;
9256
9257             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
9258             data = prefix->data;
9259             len = QT_UINT32 (data);
9260             if (len > 0x8) {
9261               len -= 0x8;
9262               buf = gst_buffer_new_and_alloc (len);
9263               gst_buffer_fill (buf, 0, data + 8, len);
9264               gst_caps_set_simple (stream->caps,
9265                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9266               gst_buffer_unref (buf);
9267             }
9268           }
9269           break;
9270         }
9271         case FOURCC_SVQ3:
9272         case FOURCC_VP31:
9273         {
9274           GstBuffer *buf;
9275           GstBuffer *seqh = NULL;
9276           guint8 *gamma_data = NULL;
9277           gint len = QT_UINT32 (stsd_data);
9278
9279           qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
9280           if (gamma_data) {
9281             gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
9282                 QT_FP32 (gamma_data), NULL);
9283           }
9284           if (seqh) {
9285             /* sorry for the bad name, but we don't know what this is, other
9286              * than its own fourcc */
9287             gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
9288                 NULL);
9289           }
9290
9291           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
9292           buf = gst_buffer_new_and_alloc (len);
9293           gst_buffer_fill (buf, 0, stsd_data, len);
9294           gst_caps_set_simple (stream->caps,
9295               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9296           gst_buffer_unref (buf);
9297           break;
9298         }
9299         case FOURCC_rle_:
9300         case FOURCC_WRLE:
9301         {
9302           gst_caps_set_simple (stream->caps,
9303               "depth", G_TYPE_INT, QT_UINT16 (stsd_data + offset + 82), NULL);
9304           break;
9305         }
9306         case FOURCC_XiTh:
9307         {
9308           GNode *xith, *xdxt;
9309
9310           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
9311           xith = qtdemux_tree_get_child_by_type (stsd, FOURCC_XiTh);
9312           if (!xith)
9313             break;
9314
9315           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
9316           if (!xdxt)
9317             break;
9318
9319           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
9320           /* collect the headers and store them in a stream list so that we can
9321            * send them out first */
9322           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
9323           break;
9324         }
9325         case FOURCC_ovc1:
9326         {
9327           GNode *ovc1;
9328           guint8 *ovc1_data;
9329           guint ovc1_len;
9330           GstBuffer *buf;
9331
9332           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
9333           ovc1 = qtdemux_tree_get_child_by_type (stsd, FOURCC_ovc1);
9334           if (!ovc1)
9335             break;
9336           ovc1_data = ovc1->data;
9337           ovc1_len = QT_UINT32 (ovc1_data);
9338           if (ovc1_len <= 198) {
9339             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
9340             break;
9341           }
9342           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
9343           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
9344           gst_caps_set_simple (stream->caps,
9345               "codec_data", GST_TYPE_BUFFER, buf, NULL);
9346           gst_buffer_unref (buf);
9347           break;
9348         }
9349         case GST_MAKE_FOURCC ('v', 'c', '-', '1'):
9350         {
9351           gint len = QT_UINT32 (stsd_data) - 0x66;
9352           const guint8 *vc1_data = stsd_data + 0x66;
9353
9354           /* find dvc1 */
9355           while (len >= 8) {
9356             gint size;
9357
9358             if (QT_UINT32 (vc1_data) <= len)
9359               size = QT_UINT32 (vc1_data) - 8;
9360             else
9361               size = len - 8;
9362
9363             if (size < 1)
9364               /* No real data, so break out */
9365               break;
9366
9367             switch (QT_FOURCC (vc1_data + 0x4)) {
9368               case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
9369               {
9370                 GstBuffer *buf;
9371
9372                 GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
9373                 buf = gst_buffer_new_and_alloc (size);
9374                 gst_buffer_fill (buf, 0, vc1_data + 8, size);
9375                 gst_caps_set_simple (stream->caps,
9376                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9377                 gst_buffer_unref (buf);
9378                 break;
9379               }
9380               default:
9381                 break;
9382             }
9383             len -= size + 8;
9384             vc1_data += size + 8;
9385           }
9386           break;
9387         }
9388         default:
9389           break;
9390       }
9391     }
9392
9393     GST_INFO_OBJECT (qtdemux,
9394         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9395         GST_FOURCC_ARGS (fourcc), stream->caps);
9396
9397   } else if (stream->subtype == FOURCC_soun) {
9398     int version, samplesize;
9399     guint16 compression_id;
9400     gboolean amrwb = FALSE;
9401
9402     offset = 32;
9403     /* sample description entry (16) + sound sample description v0 (20) */
9404     if (len < 36)
9405       goto corrupt_file;
9406
9407     version = QT_UINT32 (stsd_data + offset);
9408     stream->n_channels = QT_UINT16 (stsd_data + offset + 8);
9409     samplesize = QT_UINT16 (stsd_data + offset + 10);
9410     compression_id = QT_UINT16 (stsd_data + offset + 12);
9411     stream->rate = QT_FP32 (stsd_data + offset + 16);
9412
9413     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
9414     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
9415         QT_UINT32 (stsd_data + offset + 4));
9416     GST_LOG_OBJECT (qtdemux, "n_channels:       %d", stream->n_channels);
9417     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
9418     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
9419     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
9420         QT_UINT16 (stsd_data + offset + 14));
9421     GST_LOG_OBJECT (qtdemux, "sample rate:      %g", stream->rate);
9422
9423     if (compression_id == 0xfffe)
9424       stream->sampled = TRUE;
9425
9426     /* first assume uncompressed audio */
9427     stream->bytes_per_sample = samplesize / 8;
9428     stream->samples_per_frame = stream->n_channels;
9429     stream->bytes_per_frame = stream->n_channels * stream->bytes_per_sample;
9430     stream->samples_per_packet = stream->samples_per_frame;
9431     stream->bytes_per_packet = stream->bytes_per_sample;
9432
9433     offset = 52;
9434     switch (fourcc) {
9435         /* Yes, these have to be hard-coded */
9436       case FOURCC_MAC6:
9437       {
9438         stream->samples_per_packet = 6;
9439         stream->bytes_per_packet = 1;
9440         stream->bytes_per_frame = 1 * stream->n_channels;
9441         stream->bytes_per_sample = 1;
9442         stream->samples_per_frame = 6 * stream->n_channels;
9443         break;
9444       }
9445       case FOURCC_MAC3:
9446       {
9447         stream->samples_per_packet = 3;
9448         stream->bytes_per_packet = 1;
9449         stream->bytes_per_frame = 1 * stream->n_channels;
9450         stream->bytes_per_sample = 1;
9451         stream->samples_per_frame = 3 * stream->n_channels;
9452         break;
9453       }
9454       case FOURCC_ima4:
9455       {
9456         stream->samples_per_packet = 64;
9457         stream->bytes_per_packet = 34;
9458         stream->bytes_per_frame = 34 * stream->n_channels;
9459         stream->bytes_per_sample = 2;
9460         stream->samples_per_frame = 64 * stream->n_channels;
9461         break;
9462       }
9463       case FOURCC_ulaw:
9464       case FOURCC_alaw:
9465       {
9466         stream->samples_per_packet = 1;
9467         stream->bytes_per_packet = 1;
9468         stream->bytes_per_frame = 1 * stream->n_channels;
9469         stream->bytes_per_sample = 1;
9470         stream->samples_per_frame = 1 * stream->n_channels;
9471         break;
9472       }
9473       case FOURCC_agsm:
9474       {
9475         stream->samples_per_packet = 160;
9476         stream->bytes_per_packet = 33;
9477         stream->bytes_per_frame = 33 * stream->n_channels;
9478         stream->bytes_per_sample = 2;
9479         stream->samples_per_frame = 160 * stream->n_channels;
9480         break;
9481       }
9482       default:
9483         break;
9484     }
9485
9486     if (version == 0x00010000) {
9487       /* sample description entry (16) + sound sample description v1 (20+16) */
9488       if (len < 52)
9489         goto corrupt_file;
9490
9491       switch (fourcc) {
9492         case FOURCC_twos:
9493         case FOURCC_sowt:
9494         case FOURCC_raw_:
9495           break;
9496         default:
9497         {
9498           /* only parse extra decoding config for non-pcm audio */
9499           stream->samples_per_packet = QT_UINT32 (stsd_data + offset);
9500           stream->bytes_per_packet = QT_UINT32 (stsd_data + offset + 4);
9501           stream->bytes_per_frame = QT_UINT32 (stsd_data + offset + 8);
9502           stream->bytes_per_sample = QT_UINT32 (stsd_data + offset + 12);
9503
9504           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
9505               stream->samples_per_packet);
9506           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
9507               stream->bytes_per_packet);
9508           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
9509               stream->bytes_per_frame);
9510           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
9511               stream->bytes_per_sample);
9512
9513           if (!stream->sampled && stream->bytes_per_packet) {
9514             stream->samples_per_frame = (stream->bytes_per_frame /
9515                 stream->bytes_per_packet) * stream->samples_per_packet;
9516             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
9517                 stream->samples_per_frame);
9518           }
9519           break;
9520         }
9521       }
9522     } else if (version == 0x00020000) {
9523       union
9524       {
9525         gdouble fp;
9526         guint64 val;
9527       } qtfp;
9528
9529       /* sample description entry (16) + sound sample description v2 (56) */
9530       if (len < 72)
9531         goto corrupt_file;
9532
9533       qtfp.val = QT_UINT64 (stsd_data + offset + 4);
9534       stream->rate = qtfp.fp;
9535       stream->n_channels = QT_UINT32 (stsd_data + offset + 12);
9536
9537       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
9538       GST_LOG_OBJECT (qtdemux, "sample rate:        %g", stream->rate);
9539       GST_LOG_OBJECT (qtdemux, "n_channels:         %d", stream->n_channels);
9540       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
9541           QT_UINT32 (stsd_data + offset + 20));
9542       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
9543           QT_UINT32 (stsd_data + offset + 24));
9544       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
9545           QT_UINT32 (stsd_data + offset + 28));
9546       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
9547           QT_UINT32 (stsd_data + offset + 32));
9548     } else if (version != 0x00000) {
9549       GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x", version);
9550     }
9551
9552     if (stream->caps)
9553       gst_caps_unref (stream->caps);
9554
9555     stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc,
9556         stsd_data + 32, len - 16, &codec);
9557
9558     switch (fourcc) {
9559       case FOURCC_in24:
9560       {
9561         GNode *enda;
9562         GNode *in24;
9563
9564         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
9565
9566         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
9567         if (!enda) {
9568           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
9569           if (wave)
9570             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
9571         }
9572         if (enda) {
9573           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
9574           gst_caps_set_simple (stream->caps,
9575               "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE", NULL);
9576         }
9577         break;
9578       }
9579       case FOURCC_owma:
9580       {
9581         GNode *owma;
9582         const guint8 *owma_data;
9583         const gchar *codec_name = NULL;
9584         guint owma_len;
9585         GstBuffer *buf;
9586         gint version = 1;
9587         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9588         /* FIXME this should also be gst_riff_strf_auds,
9589          * but the latter one is actually missing bits-per-sample :( */
9590         typedef struct
9591         {
9592           gint16 wFormatTag;
9593           gint16 nChannels;
9594           gint32 nSamplesPerSec;
9595           gint32 nAvgBytesPerSec;
9596           gint16 nBlockAlign;
9597           gint16 wBitsPerSample;
9598           gint16 cbSize;
9599         } WAVEFORMATEX;
9600         WAVEFORMATEX *wfex;
9601
9602         GST_DEBUG_OBJECT (qtdemux, "parse owma");
9603         owma = qtdemux_tree_get_child_by_type (stsd, FOURCC_owma);
9604         if (!owma)
9605           break;
9606         owma_data = owma->data;
9607         owma_len = QT_UINT32 (owma_data);
9608         if (owma_len <= 54) {
9609           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
9610           break;
9611         }
9612         wfex = (WAVEFORMATEX *) (owma_data + 36);
9613         buf = gst_buffer_new_and_alloc (owma_len - 54);
9614         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
9615         if (wfex->wFormatTag == 0x0161) {
9616           codec_name = "Windows Media Audio";
9617           version = 2;
9618         } else if (wfex->wFormatTag == 0x0162) {
9619           codec_name = "Windows Media Audio 9 Pro";
9620           version = 3;
9621         } else if (wfex->wFormatTag == 0x0163) {
9622           codec_name = "Windows Media Audio 9 Lossless";
9623           /* is that correct? gstffmpegcodecmap.c is missing it, but
9624            * fluendo codec seems to support it */
9625           version = 4;
9626         }
9627
9628         gst_caps_set_simple (stream->caps,
9629             "codec_data", GST_TYPE_BUFFER, buf,
9630             "wmaversion", G_TYPE_INT, version,
9631             "block_align", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->nBlockAlign),
9632             "bitrate", G_TYPE_INT, GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec),
9633             "width", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9634             "depth", G_TYPE_INT, GST_READ_UINT16_LE (&wfex->wBitsPerSample),
9635             NULL);
9636         gst_buffer_unref (buf);
9637
9638         if (codec_name) {
9639           g_free (codec);
9640           codec = g_strdup (codec_name);
9641         }
9642         break;
9643       }
9644       case GST_MAKE_FOURCC ('w', 'm', 'a', ' '):
9645       {
9646         gint len = QT_UINT32 (stsd_data) - offset;
9647         const guint8 *wfex_data = stsd_data + offset;
9648         const gchar *codec_name = NULL;
9649         gint version = 1;
9650         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
9651         /* FIXME this should also be gst_riff_strf_auds,
9652          * but the latter one is actually missing bits-per-sample :( */
9653         typedef struct
9654         {
9655           gint16 wFormatTag;
9656           gint16 nChannels;
9657           gint32 nSamplesPerSec;
9658           gint32 nAvgBytesPerSec;
9659           gint16 nBlockAlign;
9660           gint16 wBitsPerSample;
9661           gint16 cbSize;
9662         } WAVEFORMATEX;
9663         WAVEFORMATEX wfex;
9664
9665         /* FIXME: unify with similar wavformatex parsing code above */
9666         GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
9667
9668         /* find wfex */
9669         while (len >= 8) {
9670           gint size;
9671
9672           if (QT_UINT32 (wfex_data) <= len)
9673             size = QT_UINT32 (wfex_data) - 8;
9674           else
9675             size = len - 8;
9676
9677           if (size < 1)
9678             /* No real data, so break out */
9679             break;
9680
9681           switch (QT_FOURCC (wfex_data + 4)) {
9682             case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
9683             {
9684               GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
9685
9686               if (size < 8 + 18)
9687                 break;
9688
9689               wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
9690               wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
9691               wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
9692               wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
9693               wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
9694               wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
9695               wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
9696
9697               GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
9698               GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
9699                   "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
9700                   "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
9701                   wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
9702                   wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
9703
9704               if (wfex.wFormatTag == 0x0161) {
9705                 codec_name = "Windows Media Audio";
9706                 version = 2;
9707               } else if (wfex.wFormatTag == 0x0162) {
9708                 codec_name = "Windows Media Audio 9 Pro";
9709                 version = 3;
9710               } else if (wfex.wFormatTag == 0x0163) {
9711                 codec_name = "Windows Media Audio 9 Lossless";
9712                 /* is that correct? gstffmpegcodecmap.c is missing it, but
9713                  * fluendo codec seems to support it */
9714                 version = 4;
9715               }
9716
9717               gst_caps_set_simple (stream->caps,
9718                   "wmaversion", G_TYPE_INT, version,
9719                   "block_align", G_TYPE_INT, wfex.nBlockAlign,
9720                   "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
9721                   "width", G_TYPE_INT, wfex.wBitsPerSample,
9722                   "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
9723
9724               if (size > wfex.cbSize) {
9725                 GstBuffer *buf;
9726
9727                 buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
9728                 gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
9729                     size - wfex.cbSize);
9730                 gst_caps_set_simple (stream->caps,
9731                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
9732                 gst_buffer_unref (buf);
9733               } else {
9734                 GST_WARNING_OBJECT (qtdemux, "no codec data");
9735               }
9736
9737               if (codec_name) {
9738                 g_free (codec);
9739                 codec = g_strdup (codec_name);
9740               }
9741               break;
9742             }
9743             default:
9744               break;
9745           }
9746           len -= size + 8;
9747           wfex_data += size + 8;
9748         }
9749         break;
9750       }
9751       default:
9752         break;
9753     }
9754
9755     if (codec) {
9756       GstStructure *s;
9757       gint bitrate = 0;
9758
9759       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9760           GST_TAG_AUDIO_CODEC, codec, NULL);
9761       g_free (codec);
9762       codec = NULL;
9763
9764       /* some bitrate info may have ended up in caps */
9765       s = gst_caps_get_structure (stream->caps, 0);
9766       gst_structure_get_int (s, "bitrate", &bitrate);
9767       if (bitrate > 0)
9768         gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9769             GST_TAG_BITRATE, bitrate, NULL);
9770     }
9771
9772     if (stream->protected && fourcc == FOURCC_mp4a)
9773       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_enca);
9774     else
9775       mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
9776
9777     wave = NULL;
9778     esds = NULL;
9779     if (mp4a) {
9780       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
9781       if (wave)
9782         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
9783       if (!esds)
9784         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
9785     }
9786
9787
9788     /* If the fourcc's bottom 16 bits gives 'sm', then the top
9789        16 bits is a byte-swapped wave-style codec identifier,
9790        and we can find a WAVE header internally to a 'wave' atom here.
9791        This can more clearly be thought of as 'ms' as the top 16 bits, and a
9792        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
9793        is big-endian).
9794      */
9795     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
9796       if (len < offset + 20) {
9797         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
9798       } else {
9799         guint32 datalen = QT_UINT32 (stsd_data + offset + 16);
9800         const guint8 *data = stsd_data + offset + 16;
9801         GNode *wavenode;
9802         GNode *waveheadernode;
9803
9804         wavenode = g_node_new ((guint8 *) data);
9805         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
9806           const guint8 *waveheader;
9807           guint32 headerlen;
9808
9809           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
9810           if (waveheadernode) {
9811             waveheader = (const guint8 *) waveheadernode->data;
9812             headerlen = QT_UINT32 (waveheader);
9813
9814             if (headerlen > 8) {
9815               gst_riff_strf_auds *header = NULL;
9816               GstBuffer *headerbuf;
9817               GstBuffer *extra;
9818
9819               waveheader += 8;
9820               headerlen -= 8;
9821
9822               headerbuf = gst_buffer_new_and_alloc (headerlen);
9823               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
9824
9825               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
9826                       headerbuf, &header, &extra)) {
9827                 gst_caps_unref (stream->caps);
9828                 /* FIXME: Need to do something with the channel reorder map */
9829                 stream->caps = gst_riff_create_audio_caps (header->format, NULL,
9830                     header, extra, NULL, NULL, NULL);
9831
9832                 if (extra)
9833                   gst_buffer_unref (extra);
9834                 g_free (header);
9835               }
9836             }
9837           } else
9838             GST_DEBUG ("Didn't find waveheadernode for this codec");
9839         }
9840         g_node_destroy (wavenode);
9841       }
9842     } else if (esds) {
9843       gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
9844     } else {
9845       switch (fourcc) {
9846 #if 0
9847           /* FIXME: what is in the chunk? */
9848         case FOURCC_QDMC:
9849         {
9850           gint len = QT_UINT32 (stsd_data);
9851
9852           /* seems to be always = 116 = 0x74 */
9853           break;
9854         }
9855 #endif
9856         case FOURCC_QDM2:
9857         {
9858           gint len = QT_UINT32 (stsd_data);
9859
9860           if (len > 0x4C) {
9861             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
9862
9863             gst_buffer_fill (buf, 0, stsd_data + 0x4C, len - 0x4C);
9864             gst_caps_set_simple (stream->caps,
9865                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
9866             gst_buffer_unref (buf);
9867           }
9868           gst_caps_set_simple (stream->caps,
9869               "samplesize", G_TYPE_INT, samplesize, NULL);
9870           break;
9871         }
9872         case FOURCC_alac:
9873         {
9874           GNode *alac, *wave = NULL;
9875
9876           /* apparently, m4a has this atom appended directly in the stsd entry,
9877            * while mov has it in a wave atom */
9878           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
9879           if (alac) {
9880             /* alac now refers to stsd entry atom */
9881             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
9882             if (wave)
9883               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
9884             else
9885               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
9886           }
9887           if (alac) {
9888             const guint8 *alac_data = alac->data;
9889             gint len = QT_UINT32 (alac->data);
9890             GstBuffer *buf;
9891
9892             if (len < 36) {
9893               GST_DEBUG_OBJECT (qtdemux,
9894                   "discarding alac atom with unexpected len %d", len);
9895             } else {
9896               /* codec-data contains alac atom size and prefix,
9897                * ffmpeg likes it that way, not quite gst-ish though ...*/
9898               buf = gst_buffer_new_and_alloc (len);
9899               gst_buffer_fill (buf, 0, alac->data, len);
9900               gst_caps_set_simple (stream->caps,
9901                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9902               gst_buffer_unref (buf);
9903
9904               stream->bytes_per_frame = QT_UINT32 (alac_data + 12);
9905               stream->n_channels = QT_UINT8 (alac_data + 21);
9906               stream->rate = QT_UINT32 (alac_data + 32);
9907             }
9908           }
9909           gst_caps_set_simple (stream->caps,
9910               "samplesize", G_TYPE_INT, samplesize, NULL);
9911           break;
9912         }
9913         case FOURCC_sawb:
9914           /* Fallthrough! */
9915           amrwb = TRUE;
9916         case FOURCC_samr:
9917         {
9918           gint len = QT_UINT32 (stsd_data);
9919
9920           if (len > 0x34) {
9921             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
9922             guint bitrate;
9923
9924             gst_buffer_fill (buf, 0, stsd_data + 0x34, len - 0x34);
9925
9926             /* If we have enough data, let's try to get the 'damr' atom. See
9927              * the 3GPP container spec (26.244) for more details. */
9928             if ((len - 0x34) > 8 &&
9929                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
9930               gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
9931                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
9932             }
9933
9934             gst_caps_set_simple (stream->caps,
9935                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
9936             gst_buffer_unref (buf);
9937           }
9938           break;
9939         }
9940         case FOURCC_mp4a:
9941         {
9942           /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
9943           gint len = QT_UINT32 (stsd_data);
9944
9945           if (len >= 50) {
9946             guint16 sound_version = QT_UINT16 (stsd_data + 32);
9947
9948             if (sound_version == 1) {
9949               guint16 channels = QT_UINT16 (stsd_data + 40);
9950               guint32 time_scale = QT_UINT32 (stsd_data + 46);
9951               guint8 codec_data[2];
9952               GstBuffer *buf;
9953               gint profile = 2; /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
9954
9955               gint sample_rate_index =
9956                   gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
9957
9958               /* build AAC codec data */
9959               codec_data[0] = profile << 3;
9960               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
9961               codec_data[1] = (sample_rate_index & 0x01) << 7;
9962               codec_data[1] |= (channels & 0xF) << 3;
9963
9964               buf = gst_buffer_new_and_alloc (2);
9965               gst_buffer_fill (buf, 0, codec_data, 2);
9966               gst_caps_set_simple (stream->caps,
9967                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
9968               gst_buffer_unref (buf);
9969             }
9970           }
9971           break;
9972         }
9973         default:
9974           GST_INFO_OBJECT (qtdemux,
9975               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
9976           break;
9977       }
9978     }
9979     GST_INFO_OBJECT (qtdemux,
9980         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
9981         GST_FOURCC_ARGS (fourcc), stream->caps);
9982
9983   } else if (stream->subtype == FOURCC_strm) {
9984     if (fourcc == FOURCC_rtsp) {
9985       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
9986     } else {
9987       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
9988           GST_FOURCC_ARGS (fourcc));
9989       goto unknown_stream;
9990     }
9991     stream->sampled = TRUE;
9992   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9993       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
9994
9995     stream->sampled = TRUE;
9996     stream->sparse = TRUE;
9997
9998     stream->caps =
9999         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10000     if (codec) {
10001       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10002           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10003       g_free (codec);
10004       codec = NULL;
10005     }
10006
10007     /* hunt for sort-of codec data */
10008     switch (fourcc) {
10009       case FOURCC_mp4s:
10010       {
10011         GNode *mp4s = NULL;
10012         GNode *esds = NULL;
10013
10014         /* look for palette in a stsd->mp4s->esds sub-atom */
10015         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
10016         if (mp4s)
10017           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
10018         if (esds == NULL) {
10019           /* Invalid STSD */
10020           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
10021           break;
10022         }
10023
10024         gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
10025         break;
10026       }
10027       default:
10028         GST_INFO_OBJECT (qtdemux,
10029             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
10030         break;
10031     }
10032     GST_INFO_OBJECT (qtdemux,
10033         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10034         GST_FOURCC_ARGS (fourcc), stream->caps);
10035   } else {
10036     /* everything in 1 sample */
10037     stream->sampled = TRUE;
10038
10039     stream->caps =
10040         qtdemux_generic_caps (qtdemux, stream, fourcc, stsd_data, &codec);
10041
10042     if (stream->caps == NULL)
10043       goto unknown_stream;
10044
10045     if (codec) {
10046       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10047           GST_TAG_SUBTITLE_CODEC, codec, NULL);
10048       g_free (codec);
10049       codec = NULL;
10050     }
10051   }
10052
10053   /* promote to sampled format */
10054   if (stream->fourcc == FOURCC_samr) {
10055     /* force mono 8000 Hz for AMR */
10056     stream->sampled = TRUE;
10057     stream->n_channels = 1;
10058     stream->rate = 8000;
10059   } else if (stream->fourcc == FOURCC_sawb) {
10060     /* force mono 16000 Hz for AMR-WB */
10061     stream->sampled = TRUE;
10062     stream->n_channels = 1;
10063     stream->rate = 16000;
10064   } else if (stream->fourcc == FOURCC_mp4a) {
10065     stream->sampled = TRUE;
10066   }
10067
10068   /* collect sample information */
10069   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
10070     goto samples_failed;
10071
10072   if (qtdemux->fragmented) {
10073     guint32 dummy;
10074     guint64 offset;
10075
10076     /* need all moov samples as basis; probably not many if any at all */
10077     /* prevent moof parsing taking of at this time */
10078     offset = qtdemux->moof_offset;
10079     qtdemux->moof_offset = 0;
10080     if (stream->n_samples &&
10081         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
10082       qtdemux->moof_offset = offset;
10083       goto samples_failed;
10084     }
10085     qtdemux->moof_offset = 0;
10086     /* movie duration more reliable in this case (e.g. mehd) */
10087     if (qtdemux->segment.duration &&
10088         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
10089       stream->duration =
10090           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
10091     /* need defaults for fragments */
10092     qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10093   }
10094
10095   /* configure segments */
10096   if (!qtdemux_parse_segments (qtdemux, stream, trak))
10097     goto segments_failed;
10098
10099   /* add some language tag, if useful */
10100   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
10101       strcmp (stream->lang_id, "und")) {
10102     const gchar *lang_code;
10103
10104     /* convert ISO 639-2 code to ISO 639-1 */
10105     lang_code = gst_tag_get_language_code (stream->lang_id);
10106     gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10107         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
10108   }
10109
10110   /* Check for UDTA tags */
10111   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
10112     qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
10113   }
10114
10115   /* now we are ready to add the stream */
10116   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
10117     goto too_many_streams;
10118
10119   if (!qtdemux->got_moov) {
10120     qtdemux->streams[qtdemux->n_streams] = stream;
10121     qtdemux->n_streams++;
10122     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
10123   }
10124
10125   return TRUE;
10126
10127 /* ERRORS */
10128 skip_track:
10129   {
10130     GST_INFO_OBJECT (qtdemux, "skip disabled track");
10131     if (new_stream)
10132       gst_qtdemux_stream_free (qtdemux, stream);
10133     return TRUE;
10134   }
10135 corrupt_file:
10136   {
10137     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10138         (_("This file is corrupt and cannot be played.")), (NULL));
10139     if (new_stream)
10140       gst_qtdemux_stream_free (qtdemux, stream);
10141     return FALSE;
10142   }
10143 error_encrypted:
10144   {
10145     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
10146     if (new_stream)
10147       gst_qtdemux_stream_free (qtdemux, stream);
10148     return FALSE;
10149   }
10150 samples_failed:
10151 segments_failed:
10152   {
10153     /* we posted an error already */
10154     /* free stbl sub-atoms */
10155     gst_qtdemux_stbl_free (stream);
10156     if (new_stream)
10157       gst_qtdemux_stream_free (qtdemux, stream);
10158     return FALSE;
10159   }
10160 existing_stream:
10161   {
10162     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
10163         track_id);
10164     if (new_stream)
10165       gst_qtdemux_stream_free (qtdemux, stream);
10166     return TRUE;
10167   }
10168 unknown_stream:
10169   {
10170     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
10171         GST_FOURCC_ARGS (stream->subtype));
10172     if (new_stream)
10173       gst_qtdemux_stream_free (qtdemux, stream);
10174     return TRUE;
10175   }
10176 too_many_streams:
10177   {
10178     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10179         (_("This file contains too many streams. Only playing first %d"),
10180             GST_QTDEMUX_MAX_STREAMS), (NULL));
10181     return TRUE;
10182   }
10183 }
10184
10185 /* If we can estimate the overall bitrate, and don't have information about the
10186  * stream bitrate for exactly one stream, this guesses the stream bitrate as
10187  * the overall bitrate minus the sum of the bitrates of all other streams. This
10188  * should be useful for the common case where we have one audio and one video
10189  * stream and can estimate the bitrate of one, but not the other. */
10190 static void
10191 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
10192 {
10193   QtDemuxStream *stream = NULL;
10194   gint64 size, sys_bitrate, sum_bitrate = 0;
10195   GstClockTime duration;
10196   gint i;
10197   guint bitrate;
10198
10199   if (qtdemux->fragmented)
10200     return;
10201
10202   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
10203
10204   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
10205       || size <= 0) {
10206     GST_DEBUG_OBJECT (qtdemux,
10207         "Size in bytes of the stream not known - bailing");
10208     return;
10209   }
10210
10211   /* Subtract the header size */
10212   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
10213       size, qtdemux->header_size);
10214
10215   if (size < qtdemux->header_size)
10216     return;
10217
10218   size = size - qtdemux->header_size;
10219
10220   if (!gst_qtdemux_get_duration (qtdemux, &duration) ||
10221       duration == GST_CLOCK_TIME_NONE) {
10222     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
10223     return;
10224   }
10225
10226   for (i = 0; i < qtdemux->n_streams; i++) {
10227     switch (qtdemux->streams[i]->subtype) {
10228       case FOURCC_soun:
10229       case FOURCC_vide:
10230         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
10231             qtdemux->streams[i]->caps);
10232         /* retrieve bitrate, prefer avg then max */
10233         bitrate = 0;
10234         if (qtdemux->streams[i]->pending_tags) {
10235           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10236               GST_TAG_MAXIMUM_BITRATE, &bitrate);
10237           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
10238           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10239               GST_TAG_NOMINAL_BITRATE, &bitrate);
10240           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
10241           gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
10242               GST_TAG_BITRATE, &bitrate);
10243           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
10244         }
10245         if (bitrate)
10246           sum_bitrate += bitrate;
10247         else {
10248           if (stream) {
10249             GST_DEBUG_OBJECT (qtdemux,
10250                 ">1 stream with unknown bitrate - bailing");
10251             return;
10252           } else
10253             stream = qtdemux->streams[i];
10254         }
10255
10256       default:
10257         /* For other subtypes, we assume no significant impact on bitrate */
10258         break;
10259     }
10260   }
10261
10262   if (!stream) {
10263     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
10264     return;
10265   }
10266
10267   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
10268
10269   if (sys_bitrate < sum_bitrate) {
10270     /* This can happen, since sum_bitrate might be derived from maximum
10271      * bitrates and not average bitrates */
10272     GST_DEBUG_OBJECT (qtdemux,
10273         "System bitrate less than sum bitrate - bailing");
10274     return;
10275   }
10276
10277   bitrate = sys_bitrate - sum_bitrate;
10278   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
10279       ", Stream bitrate = %u", sys_bitrate, bitrate);
10280
10281   if (!stream->pending_tags)
10282     stream->pending_tags = gst_tag_list_new_empty ();
10283
10284   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
10285       GST_TAG_BITRATE, bitrate, NULL);
10286 }
10287
10288 static GstFlowReturn
10289 qtdemux_prepare_streams (GstQTDemux * qtdemux)
10290 {
10291   gint i;
10292   GstFlowReturn ret = GST_FLOW_OK;
10293
10294   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
10295
10296   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10297     QtDemuxStream *stream = qtdemux->streams[i];
10298     guint32 sample_num = 0;
10299
10300     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10301         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10302
10303     if (qtdemux->fragmented) {
10304       /* need all moov samples first */
10305       GST_OBJECT_LOCK (qtdemux);
10306       while (stream->n_samples == 0)
10307         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
10308           break;
10309       GST_OBJECT_UNLOCK (qtdemux);
10310     } else {
10311       /* discard any stray moof */
10312       qtdemux->moof_offset = 0;
10313     }
10314
10315     /* prepare braking */
10316     if (ret != GST_FLOW_ERROR)
10317       ret = GST_FLOW_OK;
10318
10319     /* in pull mode, we should have parsed some sample info by now;
10320      * and quite some code will not handle no samples.
10321      * in push mode, we'll just have to deal with it */
10322     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
10323       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
10324       gst_qtdemux_remove_stream (qtdemux, i);
10325       i--;
10326       continue;
10327     }
10328
10329     /* parse the initial sample for use in setting the frame rate cap */
10330     while (sample_num == 0 && sample_num < stream->n_samples) {
10331       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
10332         break;
10333       ++sample_num;
10334     }
10335     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
10336       stream->first_duration = stream->samples[0].duration;
10337       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
10338           stream->track_id, stream->first_duration);
10339     }
10340   }
10341
10342   return ret;
10343 }
10344
10345 static GstFlowReturn
10346 qtdemux_expose_streams (GstQTDemux * qtdemux)
10347 {
10348   gint i;
10349   GstFlowReturn ret = GST_FLOW_OK;
10350   GSList *oldpads = NULL;
10351   GSList *iter;
10352
10353   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
10354
10355   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
10356     QtDemuxStream *stream = qtdemux->streams[i];
10357     GstPad *oldpad = stream->pad;
10358     GstTagList *list;
10359
10360     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
10361         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
10362
10363     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
10364         stream->track_id == qtdemux->chapters_track_id) {
10365       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
10366          so that it doesn't look like a subtitle track */
10367       gst_qtdemux_remove_stream (qtdemux, i);
10368       i--;
10369       continue;
10370     }
10371
10372     /* now we have all info and can expose */
10373     list = stream->pending_tags;
10374     stream->pending_tags = NULL;
10375     if (oldpad)
10376       oldpads = g_slist_prepend (oldpads, oldpad);
10377     gst_qtdemux_add_stream (qtdemux, stream, list);
10378   }
10379
10380   gst_qtdemux_guess_bitrate (qtdemux);
10381
10382   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
10383
10384   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
10385     GstPad *oldpad = iter->data;
10386
10387     gst_pad_push_event (oldpad, gst_event_new_eos ());
10388     gst_pad_set_active (oldpad, FALSE);
10389     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
10390     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
10391     gst_object_unref (oldpad);
10392   }
10393
10394   /* check if we should post a redirect in case there is a single trak
10395    * and it is a redirecting trak */
10396   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
10397     GstMessage *m;
10398
10399     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
10400         "an external content");
10401     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
10402         gst_structure_new ("redirect",
10403             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
10404             NULL));
10405     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
10406     qtdemux->posted_redirect = TRUE;
10407   }
10408
10409   for (i = 0; i < qtdemux->n_streams; i++) {
10410     QtDemuxStream *stream = qtdemux->streams[i];
10411
10412     qtdemux_do_allocation (qtdemux, stream);
10413   }
10414
10415   qtdemux->exposed = TRUE;
10416   return ret;
10417 }
10418
10419 /* check if major or compatible brand is 3GP */
10420 static inline gboolean
10421 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
10422 {
10423   if (major) {
10424     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10425         GST_MAKE_FOURCC ('3', 'g', 0, 0));
10426   } else if (qtdemux->comp_brands != NULL) {
10427     GstMapInfo map;
10428     guint8 *data;
10429     gsize size;
10430     gboolean res = FALSE;
10431
10432     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
10433     data = map.data;
10434     size = map.size;
10435     while (size >= 4) {
10436       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
10437           GST_MAKE_FOURCC ('3', 'g', 0, 0));
10438       data += 4;
10439       size -= 4;
10440     }
10441     gst_buffer_unmap (qtdemux->comp_brands, &map);
10442     return res;
10443   } else {
10444     return FALSE;
10445   }
10446 }
10447
10448 /* check if tag is a spec'ed 3GP tag keyword storing a string */
10449 static inline gboolean
10450 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
10451 {
10452   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
10453       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
10454       || fourcc == FOURCC_albm;
10455 }
10456
10457 static void
10458 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
10459     const char *tag, const char *dummy, GNode * node)
10460 {
10461   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10462   int offset;
10463   char *name;
10464   gchar *data;
10465   gdouble longitude, latitude, altitude;
10466   gint len;
10467
10468   len = QT_UINT32 (node->data);
10469   if (len <= 14)
10470     goto short_read;
10471
10472   data = node->data;
10473   offset = 14;
10474
10475   /* TODO: language code skipped */
10476
10477   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
10478
10479   if (!name) {
10480     /* do not alarm in trivial case, but bail out otherwise */
10481     if (*(data + offset) != 0) {
10482       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
10483           "giving up", tag);
10484     }
10485   } else {
10486     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10487         GST_TAG_GEO_LOCATION_NAME, name, NULL);
10488     offset += strlen (name);
10489     g_free (name);
10490   }
10491
10492   if (len < offset + 2 + 4 + 4 + 4)
10493     goto short_read;
10494
10495   /* +1 +1 = skip null-terminator and location role byte */
10496   offset += 1 + 1;
10497   /* table in spec says unsigned, semantics say negative has meaning ... */
10498   longitude = QT_SFP32 (data + offset);
10499
10500   offset += 4;
10501   latitude = QT_SFP32 (data + offset);
10502
10503   offset += 4;
10504   altitude = QT_SFP32 (data + offset);
10505
10506   /* one invalid means all are invalid */
10507   if (longitude >= -180.0 && longitude <= 180.0 &&
10508       latitude >= -90.0 && latitude <= 90.0) {
10509     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
10510         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
10511         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
10512         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
10513   }
10514
10515   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
10516
10517   return;
10518
10519   /* ERRORS */
10520 short_read:
10521   {
10522     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
10523     return;
10524   }
10525 }
10526
10527
10528 static void
10529 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
10530     const char *tag, const char *dummy, GNode * node)
10531 {
10532   guint16 y;
10533   GDate *date;
10534   gint len;
10535
10536   len = QT_UINT32 (node->data);
10537   if (len < 14)
10538     return;
10539
10540   y = QT_UINT16 ((guint8 *) node->data + 12);
10541   if (y == 0) {
10542     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
10543     return;
10544   }
10545   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
10546
10547   date = g_date_new_dmy (1, 1, y);
10548   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10549   g_date_free (date);
10550 }
10551
10552 static void
10553 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
10554     const char *tag, const char *dummy, GNode * node)
10555 {
10556   int offset;
10557   char *tag_str = NULL;
10558   guint8 *entity;
10559   guint16 table;
10560   gint len;
10561
10562   len = QT_UINT32 (node->data);
10563   if (len <= 20)
10564     goto short_read;
10565
10566   offset = 12;
10567   entity = (guint8 *) node->data + offset;
10568   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
10569     GST_DEBUG_OBJECT (qtdemux,
10570         "classification info: %c%c%c%c invalid classification entity",
10571         entity[0], entity[1], entity[2], entity[3]);
10572     return;
10573   }
10574
10575   offset += 4;
10576   table = QT_UINT16 ((guint8 *) node->data + offset);
10577
10578   /* Language code skipped */
10579
10580   offset += 4;
10581
10582   /* Tag format: "XXXX://Y[YYYY]/classification info string"
10583    * XXXX: classification entity, fixed length 4 chars.
10584    * Y[YYYY]: classification table, max 5 chars.
10585    */
10586   tag_str = g_strdup_printf ("----://%u/%s",
10587       table, (char *) node->data + offset);
10588
10589   /* memcpy To be sure we're preserving byte order */
10590   memcpy (tag_str, entity, 4);
10591   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
10592
10593   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
10594
10595   g_free (tag_str);
10596
10597   return;
10598
10599   /* ERRORS */
10600 short_read:
10601   {
10602     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
10603     return;
10604   }
10605 }
10606
10607 static gboolean
10608 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
10609     const char *tag, const char *dummy, GNode * node)
10610 {
10611   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10612   GNode *data;
10613   char *s;
10614   int len;
10615   guint32 type;
10616   int offset;
10617   gboolean ret = TRUE;
10618   const gchar *charset = NULL;
10619
10620   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10621   if (data) {
10622     len = QT_UINT32 (data->data);
10623     type = QT_UINT32 ((guint8 *) data->data + 8);
10624     if (type == 0x00000001 && len > 16) {
10625       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
10626           env_vars);
10627       if (s) {
10628         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10629         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10630         g_free (s);
10631       } else {
10632         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10633       }
10634     }
10635   } else {
10636     len = QT_UINT32 (node->data);
10637     type = QT_UINT32 ((guint8 *) node->data + 4);
10638     if ((type >> 24) == 0xa9) {
10639       gint str_len;
10640       gint lang_code;
10641
10642       /* Type starts with the (C) symbol, so the next data is a list
10643        * of (string size(16), language code(16), string) */
10644
10645       str_len = QT_UINT16 ((guint8 *) node->data + 8);
10646       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
10647
10648       /* the string + fourcc + size + 2 16bit fields,
10649        * means that there are more tags in this atom */
10650       if (len > str_len + 8 + 4) {
10651         /* TODO how to represent the same tag in different languages? */
10652         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
10653             "text alternatives, reading only first one");
10654       }
10655
10656       offset = 12;
10657       len = str_len + 8 + 4;    /* remove trailing strings that we don't use */
10658       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
10659
10660       if (lang_code < 0x800) {  /* MAC encoded string */
10661         charset = "mac";
10662       }
10663     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
10664             QT_FOURCC ((guint8 *) node->data + 4))) {
10665       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
10666
10667       /* we go for 3GP style encoding if major brands claims so,
10668        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
10669       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10670           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
10671               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
10672         offset = 14;
10673         /* 16-bit Language code is ignored here as well */
10674         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
10675       } else {
10676         goto normal;
10677       }
10678     } else {
10679     normal:
10680       offset = 8;
10681       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
10682       ret = FALSE;              /* may have to fallback */
10683     }
10684     if (charset) {
10685       GError *err = NULL;
10686
10687       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
10688           charset, NULL, NULL, &err);
10689       if (err) {
10690         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
10691             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
10692             err->message);
10693         g_error_free (err);
10694       }
10695     } else {
10696       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10697           len - offset, env_vars);
10698     }
10699     if (s) {
10700       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
10701       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
10702       g_free (s);
10703       ret = TRUE;
10704     } else {
10705       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
10706     }
10707   }
10708   return ret;
10709 }
10710
10711 static void
10712 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
10713     const char *tag, const char *dummy, GNode * node)
10714 {
10715   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
10716 }
10717
10718 static void
10719 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
10720     const char *tag, const char *dummy, GNode * node)
10721 {
10722   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
10723   guint8 *data;
10724   char *s, *t, *k = NULL;
10725   int len;
10726   int offset;
10727   int count;
10728
10729   /* first try normal string tag if major brand not 3GP */
10730   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
10731     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
10732       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
10733        * let's try it 3gpp way after minor safety check */
10734       data = node->data;
10735       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
10736         return;
10737     } else
10738       return;
10739   }
10740
10741   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
10742
10743   data = node->data;
10744
10745   len = QT_UINT32 (data);
10746   if (len < 15)
10747     goto short_read;
10748
10749   count = QT_UINT8 (data + 14);
10750   offset = 15;
10751   for (; count; count--) {
10752     gint slen;
10753
10754     if (offset + 1 > len)
10755       goto short_read;
10756     slen = QT_UINT8 (data + offset);
10757     offset += 1;
10758     if (offset + slen > len)
10759       goto short_read;
10760     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
10761         slen, env_vars);
10762     if (s) {
10763       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
10764       if (k) {
10765         t = g_strjoin (",", k, s, NULL);
10766         g_free (s);
10767         g_free (k);
10768         k = t;
10769       } else {
10770         k = s;
10771       }
10772     } else {
10773       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
10774     }
10775     offset += slen;
10776   }
10777
10778 done:
10779   if (k) {
10780     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
10781     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
10782   }
10783   g_free (k);
10784
10785   return;
10786
10787   /* ERRORS */
10788 short_read:
10789   {
10790     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
10791     goto done;
10792   }
10793 }
10794
10795 static void
10796 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
10797     const char *tag1, const char *tag2, GNode * node)
10798 {
10799   GNode *data;
10800   int len;
10801   int type;
10802   int n1, n2;
10803
10804   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10805   if (data) {
10806     len = QT_UINT32 (data->data);
10807     type = QT_UINT32 ((guint8 *) data->data + 8);
10808     if (type == 0x00000000 && len >= 22) {
10809       n1 = QT_UINT16 ((guint8 *) data->data + 18);
10810       n2 = QT_UINT16 ((guint8 *) data->data + 20);
10811       if (n1 > 0) {
10812         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
10813         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
10814       }
10815       if (n2 > 0) {
10816         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
10817         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
10818       }
10819     }
10820   }
10821 }
10822
10823 static void
10824 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
10825     const char *tag1, const char *dummy, GNode * node)
10826 {
10827   GNode *data;
10828   int len;
10829   int type;
10830   int n1;
10831
10832   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10833   if (data) {
10834     len = QT_UINT32 (data->data);
10835     type = QT_UINT32 ((guint8 *) data->data + 8);
10836     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
10837     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
10838     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
10839       n1 = QT_UINT16 ((guint8 *) data->data + 16);
10840       if (n1) {
10841         /* do not add bpm=0 */
10842         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
10843         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
10844             NULL);
10845       }
10846     }
10847   }
10848 }
10849
10850 static void
10851 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
10852     const char *tag1, const char *dummy, GNode * node)
10853 {
10854   GNode *data;
10855   int len;
10856   int type;
10857   guint32 num;
10858
10859   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10860   if (data) {
10861     len = QT_UINT32 (data->data);
10862     type = QT_UINT32 ((guint8 *) data->data + 8);
10863     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
10864     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
10865     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
10866       num = QT_UINT32 ((guint8 *) data->data + 16);
10867       if (num) {
10868         /* do not add num=0 */
10869         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
10870         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
10871       }
10872     }
10873   }
10874 }
10875
10876 static void
10877 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
10878     const char *tag1, const char *dummy, GNode * node)
10879 {
10880   GNode *data;
10881   int len;
10882   int type;
10883   GstSample *sample;
10884
10885   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10886   if (data) {
10887     len = QT_UINT32 (data->data);
10888     type = QT_UINT32 ((guint8 *) data->data + 8);
10889     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
10890     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
10891       if ((sample =
10892               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
10893                   len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
10894         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
10895         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
10896         gst_sample_unref (sample);
10897       }
10898     }
10899   }
10900 }
10901
10902 static void
10903 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
10904     const char *tag, const char *dummy, GNode * node)
10905 {
10906   GNode *data;
10907   char *s;
10908   int len;
10909   int type;
10910
10911   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10912   if (data) {
10913     len = QT_UINT32 (data->data);
10914     type = QT_UINT32 ((guint8 *) data->data + 8);
10915     if (type == 0x00000001 && len > 16) {
10916       guint y, m = 1, d = 1;
10917       gint ret;
10918
10919       s = g_strndup ((char *) data->data + 16, len - 16);
10920       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
10921       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
10922       if (ret >= 1 && y > 1500 && y < 3000) {
10923         GDate *date;
10924
10925         date = g_date_new_dmy (d, m, y);
10926         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
10927         g_date_free (date);
10928       } else {
10929         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
10930       }
10931       g_free (s);
10932     }
10933   }
10934 }
10935
10936 static void
10937 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
10938     const char *tag, const char *dummy, GNode * node)
10939 {
10940   GNode *data;
10941
10942   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
10943
10944   /* re-route to normal string tag if major brand says so
10945    * or no data atom and compatible brand suggests so */
10946   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
10947       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
10948     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
10949     return;
10950   }
10951
10952   if (data) {
10953     guint len, type, n;
10954
10955     len = QT_UINT32 (data->data);
10956     type = QT_UINT32 ((guint8 *) data->data + 8);
10957     if (type == 0x00000000 && len >= 18) {
10958       n = QT_UINT16 ((guint8 *) data->data + 16);
10959       if (n > 0) {
10960         const gchar *genre;
10961
10962         genre = gst_tag_id3_genre_get (n - 1);
10963         if (genre != NULL) {
10964           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
10965           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
10966         }
10967       }
10968     }
10969   }
10970 }
10971
10972 static void
10973 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
10974     const gchar * tag, guint8 * data, guint32 datasize)
10975 {
10976   gdouble value;
10977   gchar *datacopy;
10978
10979   /* make a copy to have \0 at the end */
10980   datacopy = g_strndup ((gchar *) data, datasize);
10981
10982   /* convert the str to double */
10983   if (sscanf (datacopy, "%lf", &value) == 1) {
10984     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
10985     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
10986   } else {
10987     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
10988         datacopy);
10989   }
10990   g_free (datacopy);
10991 }
10992
10993
10994 static void
10995 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
10996     const char *tag, const char *tag_bis, GNode * node)
10997 {
10998   GNode *mean;
10999   GNode *name;
11000   GNode *data;
11001   guint32 meansize;
11002   guint32 namesize;
11003   guint32 datatype;
11004   guint32 datasize;
11005   const gchar *meanstr;
11006   const gchar *namestr;
11007
11008   /* checking the whole ---- atom size for consistency */
11009   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
11010     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
11011     return;
11012   }
11013
11014   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
11015   if (!mean) {
11016     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
11017     return;
11018   }
11019
11020   meansize = QT_UINT32 (mean->data);
11021   if (meansize <= 12) {
11022     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
11023     return;
11024   }
11025   meanstr = ((gchar *) mean->data) + 12;
11026   meansize -= 12;
11027
11028   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
11029   if (!name) {
11030     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
11031     return;
11032   }
11033
11034   namesize = QT_UINT32 (name->data);
11035   if (namesize <= 12) {
11036     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
11037     return;
11038   }
11039   namestr = ((gchar *) name->data) + 12;
11040   namesize -= 12;
11041
11042   /*
11043    * Data atom is:
11044    * uint32 - size
11045    * uint32 - name
11046    * uint8  - version
11047    * uint24 - data type
11048    * uint32 - all 0
11049    * rest   - the data
11050    */
11051   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
11052   if (!data) {
11053     GST_WARNING_OBJECT (demux, "No data atom in this tag");
11054     return;
11055   }
11056   datasize = QT_UINT32 (data->data);
11057   if (datasize <= 16) {
11058     GST_WARNING_OBJECT (demux, "Data atom too small");
11059     return;
11060   }
11061   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
11062
11063   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
11064       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
11065     static const struct
11066     {
11067       const gchar name[28];
11068       const gchar tag[28];
11069     } tags[] = {
11070       {
11071       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
11072       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
11073       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
11074       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
11075       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
11076       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
11077       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
11078       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
11079     };
11080     int i;
11081
11082     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
11083       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
11084         switch (gst_tag_get_type (tags[i].tag)) {
11085           case G_TYPE_DOUBLE:
11086             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
11087                 ((guint8 *) data->data) + 16, datasize - 16);
11088             break;
11089           case G_TYPE_STRING:
11090             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
11091             break;
11092           default:
11093             /* not reached */
11094             break;
11095         }
11096         break;
11097       }
11098     }
11099     if (i == G_N_ELEMENTS (tags))
11100       goto unknown_tag;
11101   } else {
11102     goto unknown_tag;
11103   }
11104
11105   return;
11106
11107 /* errors */
11108 unknown_tag:
11109 #ifndef GST_DISABLE_GST_DEBUG
11110   {
11111     gchar *namestr_dbg;
11112     gchar *meanstr_dbg;
11113
11114     meanstr_dbg = g_strndup (meanstr, meansize);
11115     namestr_dbg = g_strndup (namestr, namesize);
11116
11117     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
11118         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
11119
11120     g_free (namestr_dbg);
11121     g_free (meanstr_dbg);
11122   }
11123 #endif
11124   return;
11125 }
11126
11127 static void
11128 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
11129     const char *tag_bis, GNode * node)
11130 {
11131   guint8 *data;
11132   GstBuffer *buf;
11133   guint len;
11134   GstTagList *id32_taglist = NULL;
11135
11136   GST_LOG_OBJECT (demux, "parsing ID32");
11137
11138   data = node->data;
11139   len = GST_READ_UINT32_BE (data);
11140
11141   /* need at least full box and language tag */
11142   if (len < 12 + 2)
11143     return;
11144
11145   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
11146   gst_buffer_fill (buf, 0, data + 14, len - 14);
11147
11148   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
11149   if (id32_taglist) {
11150     GST_LOG_OBJECT (demux, "parsing ok");
11151     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
11152     gst_tag_list_unref (id32_taglist);
11153   } else {
11154     GST_LOG_OBJECT (demux, "parsing failed");
11155   }
11156
11157   gst_buffer_unref (buf);
11158 }
11159
11160 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
11161     const char *tag, const char *tag_bis, GNode * node);
11162
11163 /* unmapped tags
11164 FOURCC_pcst -> if media is a podcast -> bool
11165 FOURCC_cpil -> if media is part of a compilation -> bool
11166 FOURCC_pgap -> if media is part of a gapless context -> bool
11167 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
11168 */
11169
11170 static const struct
11171 {
11172   guint32 fourcc;
11173   const gchar *gst_tag;
11174   const gchar *gst_tag_bis;
11175   const GstQTDemuxAddTagFunc func;
11176 } add_funcs[] = {
11177   {
11178   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11179   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
11180   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
11181   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11182   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11183   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
11184   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
11185   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
11186   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11187   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
11188   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11189   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
11190   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11191   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11192   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11193   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
11194   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
11195   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
11196   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
11197   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11198   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
11199   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
11200   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11201         qtdemux_tag_add_num}, {
11202   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
11203         qtdemux_tag_add_num}, {
11204   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
11205   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
11206   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
11207   FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, qtdemux_tag_add_covr}, {
11208   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
11209   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
11210   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11211   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
11212   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
11213   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
11214   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
11215   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11216   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
11217   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
11218   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
11219   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
11220   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
11221   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
11222         qtdemux_tag_add_classification}, {
11223   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
11224   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
11225   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
11226
11227     /* This is a special case, some tags are stored in this
11228      * 'reverse dns naming', according to:
11229      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
11230      * bug #614471
11231      */
11232   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
11233     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
11234   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
11235 };
11236
11237 struct _GstQtDemuxTagList
11238 {
11239   GstQTDemux *demux;
11240   GstTagList *taglist;
11241 };
11242 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
11243
11244 static void
11245 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
11246 {
11247   gint len;
11248   guint8 *data;
11249   GstBuffer *buf;
11250   gchar *media_type;
11251   const gchar *style;
11252   GstSample *sample;
11253   GstStructure *s;
11254   guint i;
11255   guint8 ndata[4];
11256   GstQTDemux *demux = qtdemuxtaglist->demux;
11257   GstTagList *taglist = qtdemuxtaglist->taglist;
11258
11259   data = node->data;
11260   len = QT_UINT32 (data);
11261   buf = gst_buffer_new_and_alloc (len);
11262   gst_buffer_fill (buf, 0, data, len);
11263
11264   /* heuristic to determine style of tag */
11265   if (QT_FOURCC (data + 4) == FOURCC_____ ||
11266       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
11267     style = "itunes";
11268   else if (demux->major_brand == FOURCC_qt__)
11269     style = "quicktime";
11270   /* fall back to assuming iso/3gp tag style */
11271   else
11272     style = "iso";
11273
11274   /* santize the name for the caps. */
11275   for (i = 0; i < 4; i++) {
11276     guint8 d = data[4 + i];
11277     if (g_ascii_isalnum (d))
11278       ndata[i] = g_ascii_tolower (d);
11279     else
11280       ndata[i] = '_';
11281   }
11282
11283   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
11284       ndata[0], ndata[1], ndata[2], ndata[3]);
11285   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
11286
11287   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
11288   sample = gst_sample_new (buf, NULL, NULL, s);
11289   gst_buffer_unref (buf);
11290   g_free (media_type);
11291
11292   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
11293       len, s);
11294
11295   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
11296       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
11297
11298   gst_sample_unref (sample);
11299 }
11300
11301 static void
11302 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
11303 {
11304   GNode *meta;
11305   GNode *ilst;
11306   GNode *xmp_;
11307   GNode *node;
11308   gint i;
11309   GstQtDemuxTagList demuxtaglist;
11310
11311   demuxtaglist.demux = qtdemux;
11312   demuxtaglist.taglist = taglist;
11313
11314   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
11315   if (meta != NULL) {
11316     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
11317     if (ilst == NULL) {
11318       GST_LOG_OBJECT (qtdemux, "no ilst");
11319       return;
11320     }
11321   } else {
11322     ilst = udta;
11323     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
11324   }
11325
11326   i = 0;
11327   while (i < G_N_ELEMENTS (add_funcs)) {
11328     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
11329     if (node) {
11330       gint len;
11331
11332       len = QT_UINT32 (node->data);
11333       if (len < 12) {
11334         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
11335             GST_FOURCC_ARGS (add_funcs[i].fourcc));
11336       } else {
11337         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
11338             add_funcs[i].gst_tag_bis, node);
11339       }
11340       g_node_destroy (node);
11341     } else {
11342       i++;
11343     }
11344   }
11345
11346   /* parsed nodes have been removed, pass along remainder as blob */
11347   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
11348       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
11349
11350   /* parse up XMP_ node if existing */
11351   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
11352   if (xmp_ != NULL) {
11353     GstBuffer *buf;
11354     GstTagList *xmptaglist;
11355
11356     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
11357         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
11358     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
11359     gst_buffer_unref (buf);
11360
11361     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
11362   } else {
11363     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
11364   }
11365 }
11366
11367 typedef struct
11368 {
11369   GstStructure *structure;      /* helper for sort function */
11370   gchar *location;
11371   guint min_req_bitrate;
11372   guint min_req_qt_version;
11373 } GstQtReference;
11374
11375 static gint
11376 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
11377 {
11378   GstQtReference *ref_a = (GstQtReference *) a;
11379   GstQtReference *ref_b = (GstQtReference *) b;
11380
11381   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
11382     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
11383
11384   /* known bitrates go before unknown; higher bitrates go first */
11385   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
11386 }
11387
11388 /* sort the redirects and post a message for the application.
11389  */
11390 static void
11391 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
11392 {
11393   GstQtReference *best;
11394   GstStructure *s;
11395   GstMessage *msg;
11396   GValue list_val = { 0, };
11397   GList *l;
11398
11399   g_assert (references != NULL);
11400
11401   references = g_list_sort (references, qtdemux_redirects_sort_func);
11402
11403   best = (GstQtReference *) references->data;
11404
11405   g_value_init (&list_val, GST_TYPE_LIST);
11406
11407   for (l = references; l != NULL; l = l->next) {
11408     GstQtReference *ref = (GstQtReference *) l->data;
11409     GValue struct_val = { 0, };
11410
11411     ref->structure = gst_structure_new ("redirect",
11412         "new-location", G_TYPE_STRING, ref->location, NULL);
11413
11414     if (ref->min_req_bitrate > 0) {
11415       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
11416           ref->min_req_bitrate, NULL);
11417     }
11418
11419     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
11420     g_value_set_boxed (&struct_val, ref->structure);
11421     gst_value_list_append_value (&list_val, &struct_val);
11422     g_value_unset (&struct_val);
11423     /* don't free anything here yet, since we need best->structure below */
11424   }
11425
11426   g_assert (best != NULL);
11427   s = gst_structure_copy (best->structure);
11428
11429   if (g_list_length (references) > 1) {
11430     gst_structure_set_value (s, "locations", &list_val);
11431   }
11432
11433   g_value_unset (&list_val);
11434
11435   for (l = references; l != NULL; l = l->next) {
11436     GstQtReference *ref = (GstQtReference *) l->data;
11437
11438     gst_structure_free (ref->structure);
11439     g_free (ref->location);
11440     g_free (ref);
11441   }
11442   g_list_free (references);
11443
11444   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
11445   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
11446   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
11447   qtdemux->posted_redirect = TRUE;
11448 }
11449
11450 /* look for redirect nodes, collect all redirect information and
11451  * process it.
11452  */
11453 static gboolean
11454 qtdemux_parse_redirects (GstQTDemux * qtdemux)
11455 {
11456   GNode *rmra, *rmda, *rdrf;
11457
11458   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
11459   if (rmra) {
11460     GList *redirects = NULL;
11461
11462     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
11463     while (rmda) {
11464       GstQtReference ref = { NULL, NULL, 0, 0 };
11465       GNode *rmdr, *rmvc;
11466
11467       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
11468         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
11469         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
11470             ref.min_req_bitrate);
11471       }
11472
11473       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
11474         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
11475         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
11476
11477 #ifndef GST_DISABLE_GST_DEBUG
11478         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
11479 #endif
11480         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
11481
11482         GST_LOG_OBJECT (qtdemux,
11483             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
11484             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
11485             bitmask, check_type);
11486         if (package == FOURCC_qtim && check_type == 0) {
11487           ref.min_req_qt_version = version;
11488         }
11489       }
11490
11491       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
11492       if (rdrf) {
11493         guint32 ref_type;
11494         guint8 *ref_data;
11495         guint ref_len;
11496
11497         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
11498         if (ref_len > 20) {
11499           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
11500           ref_data = (guint8 *) rdrf->data + 20;
11501           if (ref_type == FOURCC_alis) {
11502             guint record_len, record_version, fn_len;
11503
11504             if (ref_len > 70) {
11505               /* MacOSX alias record, google for alias-layout.txt */
11506               record_len = QT_UINT16 (ref_data + 4);
11507               record_version = QT_UINT16 (ref_data + 4 + 2);
11508               fn_len = QT_UINT8 (ref_data + 50);
11509               if (record_len > 50 && record_version == 2 && fn_len > 0) {
11510                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
11511               }
11512             } else {
11513               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
11514                   ref_len);
11515             }
11516           } else if (ref_type == FOURCC_url_) {
11517             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
11518           } else {
11519             GST_DEBUG_OBJECT (qtdemux,
11520                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
11521                 GST_FOURCC_ARGS (ref_type));
11522           }
11523           if (ref.location != NULL) {
11524             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
11525             redirects =
11526                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
11527           } else {
11528             GST_WARNING_OBJECT (qtdemux,
11529                 "Failed to extract redirect location from rdrf atom");
11530           }
11531         } else {
11532           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
11533         }
11534       }
11535
11536       /* look for others */
11537       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
11538     }
11539
11540     if (redirects != NULL) {
11541       qtdemux_process_redirects (qtdemux, redirects);
11542     }
11543   }
11544   return TRUE;
11545 }
11546
11547 static GstTagList *
11548 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
11549 {
11550   const gchar *fmt;
11551
11552   if (tags == NULL) {
11553     tags = gst_tag_list_new_empty ();
11554     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
11555   }
11556
11557   if (qtdemux->major_brand == FOURCC_mjp2)
11558     fmt = "Motion JPEG 2000";
11559   else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
11560     fmt = "3GP";
11561   else if (qtdemux->major_brand == FOURCC_qt__)
11562     fmt = "Quicktime";
11563   else if (qtdemux->fragmented)
11564     fmt = "ISO fMP4";
11565   else
11566     fmt = "ISO MP4/M4A";
11567
11568   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
11569       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
11570
11571   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
11572       fmt, NULL);
11573
11574   return tags;
11575 }
11576
11577 /* we have read th complete moov node now.
11578  * This function parses all of the relevant info, creates the traks and
11579  * prepares all data structures for playback
11580  */
11581 static gboolean
11582 qtdemux_parse_tree (GstQTDemux * qtdemux)
11583 {
11584   GNode *mvhd;
11585   GNode *trak;
11586   GNode *udta;
11587   GNode *mvex;
11588   GstClockTime duration;
11589   GNode *pssh;
11590   guint64 creation_time;
11591   GstDateTime *datetime = NULL;
11592   gint version;
11593
11594   /* make sure we have a usable taglist */
11595   if (!qtdemux->tag_list) {
11596     qtdemux->tag_list = gst_tag_list_new_empty ();
11597     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11598   } else {
11599     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11600   }
11601
11602   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
11603   if (mvhd == NULL) {
11604     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
11605     return qtdemux_parse_redirects (qtdemux);
11606   }
11607
11608   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
11609   if (version == 1) {
11610     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
11611     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
11612     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
11613   } else if (version == 0) {
11614     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
11615     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
11616     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
11617   } else {
11618     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
11619     return FALSE;
11620   }
11621
11622   /* Moving qt creation time (secs since 1904) to unix time */
11623   if (creation_time != 0) {
11624     /* Try to use epoch first as it should be faster and more commonly found */
11625     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
11626       GTimeVal now;
11627
11628       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
11629       /* some data cleansing sanity */
11630       g_get_current_time (&now);
11631       if (now.tv_sec + 24 * 3600 < creation_time) {
11632         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
11633       } else {
11634         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
11635       }
11636     } else {
11637       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
11638       GDateTime *dt, *dt_local;
11639
11640       dt = g_date_time_add_seconds (base_dt, creation_time);
11641       dt_local = g_date_time_to_local (dt);
11642       datetime = gst_date_time_new_from_g_date_time (dt_local);
11643
11644       g_date_time_unref (base_dt);
11645       g_date_time_unref (dt);
11646     }
11647   }
11648   if (datetime) {
11649     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
11650     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
11651         datetime, NULL);
11652     gst_date_time_unref (datetime);
11653   }
11654
11655   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
11656   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
11657
11658   /* check for fragmented file and get some (default) data */
11659   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
11660   if (mvex) {
11661     GNode *mehd;
11662     GstByteReader mehd_data;
11663
11664     /* let track parsing or anyone know weird stuff might happen ... */
11665     qtdemux->fragmented = TRUE;
11666
11667     /* compensate for total duration */
11668     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
11669     if (mehd)
11670       qtdemux_parse_mehd (qtdemux, &mehd_data);
11671   }
11672
11673   /* set duration in the segment info */
11674   gst_qtdemux_get_duration (qtdemux, &duration);
11675   if (duration) {
11676     qtdemux->segment.duration = duration;
11677     /* also do not exceed duration; stop is set that way post seek anyway,
11678      * and segment activation falls back to duration,
11679      * whereas loop only checks stop, so let's align this here as well */
11680     qtdemux->segment.stop = duration;
11681   }
11682
11683   /* parse all traks */
11684   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
11685   while (trak) {
11686     qtdemux_parse_trak (qtdemux, trak);
11687     /* iterate all siblings */
11688     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
11689   }
11690
11691   if (!qtdemux->tag_list) {
11692     GST_DEBUG_OBJECT (qtdemux, "new tag list");
11693     qtdemux->tag_list = gst_tag_list_new_empty ();
11694     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
11695   } else {
11696     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
11697   }
11698
11699   /* find tags */
11700   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
11701   if (udta) {
11702     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11703   } else {
11704     GST_LOG_OBJECT (qtdemux, "No udta node found.");
11705   }
11706
11707   /* maybe also some tags in meta box */
11708   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
11709   if (udta) {
11710     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
11711     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
11712   } else {
11713     GST_LOG_OBJECT (qtdemux, "No meta node found.");
11714   }
11715
11716   /* parse any protection system info */
11717   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
11718   while (pssh) {
11719     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
11720     qtdemux_parse_pssh (qtdemux, pssh);
11721     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
11722   }
11723
11724   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
11725
11726   return TRUE;
11727 }
11728
11729 /* taken from ffmpeg */
11730 static int
11731 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
11732 {
11733   int count = 4;
11734   int len = 0;
11735
11736   while (count--) {
11737     int c;
11738
11739     if (ptr >= end)
11740       return -1;
11741
11742     c = *ptr++;
11743     len = (len << 7) | (c & 0x7f);
11744     if (!(c & 0x80))
11745       break;
11746   }
11747   *end_out = ptr;
11748   return len;
11749 }
11750
11751 /* this can change the codec originally present in @list */
11752 static void
11753 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
11754     GNode * esds, GstTagList * list)
11755 {
11756   int len = QT_UINT32 (esds->data);
11757   guint8 *ptr = esds->data;
11758   guint8 *end = ptr + len;
11759   int tag;
11760   guint8 *data_ptr = NULL;
11761   int data_len = 0;
11762   guint8 object_type_id = 0;
11763   const char *codec_name = NULL;
11764   GstCaps *caps = NULL;
11765
11766   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
11767   ptr += 8;
11768   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
11769   ptr += 4;
11770   while (ptr + 1 < end) {
11771     tag = QT_UINT8 (ptr);
11772     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
11773     ptr++;
11774     len = read_descr_size (ptr, end, &ptr);
11775     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
11776
11777     /* Check the stated amount of data is available for reading */
11778     if (len < 0 || ptr + len > end)
11779       break;
11780
11781     switch (tag) {
11782       case ES_DESCRIPTOR_TAG:
11783         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
11784         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
11785         ptr += 3;
11786         break;
11787       case DECODER_CONFIG_DESC_TAG:{
11788         guint max_bitrate, avg_bitrate;
11789
11790         object_type_id = QT_UINT8 (ptr);
11791         max_bitrate = QT_UINT32 (ptr + 5);
11792         avg_bitrate = QT_UINT32 (ptr + 9);
11793         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
11794         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
11795         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
11796         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
11797         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
11798         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11799           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
11800               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
11801         }
11802         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11803           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
11804               avg_bitrate, NULL);
11805         }
11806         ptr += 13;
11807         break;
11808       }
11809       case DECODER_SPECIFIC_INFO_TAG:
11810         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
11811         if (object_type_id == 0xe0 && len == 0x40) {
11812           guint8 *data;
11813           GstStructure *s;
11814           guint32 clut[16];
11815           gint i;
11816
11817           GST_DEBUG_OBJECT (qtdemux,
11818               "Have VOBSUB palette. Creating palette event");
11819           /* move to decConfigDescr data and read palette */
11820           data = ptr;
11821           for (i = 0; i < 16; i++) {
11822             clut[i] = QT_UINT32 (data);
11823             data += 4;
11824           }
11825
11826           s = gst_structure_new ("application/x-gst-dvd", "event",
11827               G_TYPE_STRING, "dvd-spu-clut-change",
11828               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
11829               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
11830               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
11831               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
11832               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
11833               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
11834               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
11835               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
11836               NULL);
11837
11838           /* store event and trigger custom processing */
11839           stream->pending_event =
11840               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
11841         } else {
11842           /* Generic codec_data handler puts it on the caps */
11843           data_ptr = ptr;
11844           data_len = len;
11845         }
11846
11847         ptr += len;
11848         break;
11849       case SL_CONFIG_DESC_TAG:
11850         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
11851         ptr += 1;
11852         break;
11853       default:
11854         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
11855             tag);
11856         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
11857         ptr += len;
11858         break;
11859     }
11860   }
11861
11862   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
11863    * in use, and should also be used to override some other parameters for some
11864    * codecs. */
11865   switch (object_type_id) {
11866     case 0x20:                 /* MPEG-4 */
11867       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
11868        * profile_and_level_indication */
11869       if (data_ptr != NULL && data_len >= 5 &&
11870           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
11871         gst_codec_utils_mpeg4video_caps_set_level_and_profile (stream->caps,
11872             data_ptr + 4, data_len - 4);
11873       }
11874       break;                    /* Nothing special needed here */
11875     case 0x21:                 /* H.264 */
11876       codec_name = "H.264 / AVC";
11877       caps = gst_caps_new_simple ("video/x-h264",
11878           "stream-format", G_TYPE_STRING, "avc",
11879           "alignment", G_TYPE_STRING, "au", NULL);
11880       break;
11881     case 0x40:                 /* AAC (any) */
11882     case 0x66:                 /* AAC Main */
11883     case 0x67:                 /* AAC LC */
11884     case 0x68:                 /* AAC SSR */
11885       /* Override channels and rate based on the codec_data, as it's often
11886        * wrong. */
11887       /* Only do so for basic setup without HE-AAC extension */
11888       if (data_ptr && data_len == 2) {
11889         guint channels, rateindex, rate;
11890
11891         /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
11892         channels = (data_ptr[1] & 0x7f) >> 3;
11893         if (channels > 0 && channels < 7) {
11894           stream->n_channels = channels;
11895         } else if (channels == 7) {
11896           stream->n_channels = 8;
11897         }
11898
11899         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
11900         rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
11901         if (rate > 0)
11902           stream->rate = rate;
11903       }
11904
11905       /* Set level and profile if possible */
11906       if (data_ptr != NULL && data_len >= 2) {
11907         gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
11908             data_ptr, data_len);
11909       }
11910       break;
11911     case 0x60:                 /* MPEG-2, various profiles */
11912     case 0x61:
11913     case 0x62:
11914     case 0x63:
11915     case 0x64:
11916     case 0x65:
11917       codec_name = "MPEG-2 video";
11918       caps = gst_caps_new_simple ("video/mpeg",
11919           "mpegversion", G_TYPE_INT, 2,
11920           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11921       break;
11922     case 0x69:                 /* MPEG-2 BC audio */
11923     case 0x6B:                 /* MPEG-1 audio */
11924       caps = gst_caps_new_simple ("audio/mpeg",
11925           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
11926       codec_name = "MPEG-1 audio";
11927       break;
11928     case 0x6A:                 /* MPEG-1 */
11929       codec_name = "MPEG-1 video";
11930       caps = gst_caps_new_simple ("video/mpeg",
11931           "mpegversion", G_TYPE_INT, 1,
11932           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
11933       break;
11934     case 0x6C:                 /* MJPEG */
11935       caps =
11936           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
11937           NULL);
11938       codec_name = "Motion-JPEG";
11939       break;
11940     case 0x6D:                 /* PNG */
11941       caps =
11942           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
11943           NULL);
11944       codec_name = "PNG still images";
11945       break;
11946     case 0x6E:                 /* JPEG2000 */
11947       codec_name = "JPEG-2000";
11948       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
11949       break;
11950     case 0xA4:                 /* Dirac */
11951       codec_name = "Dirac";
11952       caps = gst_caps_new_empty_simple ("video/x-dirac");
11953       break;
11954     case 0xA5:                 /* AC3 */
11955       codec_name = "AC-3 audio";
11956       caps = gst_caps_new_simple ("audio/x-ac3",
11957           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11958       break;
11959     case 0xA9:                 /* AC3 */
11960       codec_name = "DTS audio";
11961       caps = gst_caps_new_simple ("audio/x-dts",
11962           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
11963       break;
11964     case 0xE1:                 /* QCELP */
11965       /* QCELP, the codec_data is a riff tag (little endian) with
11966        * 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). */
11967       caps = gst_caps_new_empty_simple ("audio/qcelp");
11968       codec_name = "QCELP";
11969       break;
11970     default:
11971       break;
11972   }
11973
11974   /* If we have a replacement caps, then change our caps for this stream */
11975   if (caps) {
11976     gst_caps_unref (stream->caps);
11977     stream->caps = caps;
11978   }
11979
11980   if (codec_name && list)
11981     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
11982         GST_TAG_AUDIO_CODEC, codec_name, NULL);
11983
11984   /* Add the codec_data attribute to caps, if we have it */
11985   if (data_ptr) {
11986     GstBuffer *buffer;
11987
11988     buffer = gst_buffer_new_and_alloc (data_len);
11989     gst_buffer_fill (buffer, 0, data_ptr, data_len);
11990
11991     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
11992     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
11993
11994     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
11995         buffer, NULL);
11996     gst_buffer_unref (buffer);
11997   }
11998
11999 }
12000
12001 #define _codec(name) \
12002   do { \
12003     if (codec_name) { \
12004       *codec_name = g_strdup (name); \
12005     } \
12006   } while (0)
12007
12008 static GstCaps *
12009 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12010     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12011 {
12012   GstCaps *caps = NULL;
12013   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
12014
12015   switch (fourcc) {
12016     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
12017       _codec ("PNG still images");
12018       caps = gst_caps_new_empty_simple ("image/png");
12019       break;
12020     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
12021       _codec ("JPEG still images");
12022       caps =
12023           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12024           NULL);
12025       break;
12026     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
12027     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
12028     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
12029     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
12030       _codec ("Motion-JPEG");
12031       caps =
12032           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
12033           NULL);
12034       break;
12035     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
12036       _codec ("Motion-JPEG format B");
12037       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
12038       break;
12039     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
12040       _codec ("JPEG-2000");
12041       /* override to what it should be according to spec, avoid palette_data */
12042       stream->bits_per_sample = 24;
12043       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
12044       break;
12045     case GST_MAKE_FOURCC ('S', 'V', 'Q', '3'):
12046       _codec ("Sorensen video v.3");
12047       caps = gst_caps_new_simple ("video/x-svq",
12048           "svqversion", G_TYPE_INT, 3, NULL);
12049       break;
12050     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
12051     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
12052       _codec ("Sorensen video v.1");
12053       caps = gst_caps_new_simple ("video/x-svq",
12054           "svqversion", G_TYPE_INT, 1, NULL);
12055       break;
12056     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
12057       caps = gst_caps_new_empty_simple ("video/x-raw");
12058       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
12059       _codec ("Windows Raw RGB");
12060       break;
12061     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
12062     {
12063       guint16 bps;
12064
12065       bps = QT_UINT16 (stsd_data + 98);
12066       switch (bps) {
12067         case 15:
12068           format = GST_VIDEO_FORMAT_RGB15;
12069           break;
12070         case 16:
12071           format = GST_VIDEO_FORMAT_RGB16;
12072           break;
12073         case 24:
12074           format = GST_VIDEO_FORMAT_RGB;
12075           break;
12076         case 32:
12077           format = GST_VIDEO_FORMAT_ARGB;
12078           break;
12079         default:
12080           /* unknown */
12081           break;
12082       }
12083       break;
12084     }
12085     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
12086       format = GST_VIDEO_FORMAT_I420;
12087       break;
12088     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
12089     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
12090       format = GST_VIDEO_FORMAT_I420;
12091       break;
12092     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
12093     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
12094       format = GST_VIDEO_FORMAT_UYVY;
12095       break;
12096     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
12097       format = GST_VIDEO_FORMAT_v308;
12098       break;
12099     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
12100       format = GST_VIDEO_FORMAT_v216;
12101       break;
12102     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
12103       format = GST_VIDEO_FORMAT_v210;
12104       break;
12105     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
12106       format = GST_VIDEO_FORMAT_r210;
12107       break;
12108       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
12109          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
12110          format = GST_VIDEO_FORMAT_v410;
12111          break;
12112        */
12113       /* Packed YUV 4:4:4:4 8 bit in 32 bits
12114        * but different order than AYUV
12115        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
12116        format = GST_VIDEO_FORMAT_v408;
12117        break;
12118        */
12119     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
12120     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
12121       _codec ("MPEG-1 video");
12122       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12123           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12124       break;
12125     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
12126     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
12127     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
12128     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
12129     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
12130     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
12131     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
12132     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
12133     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
12134     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
12135     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
12136     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
12137     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
12138     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
12139     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
12140     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
12141     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
12142     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
12143     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
12144     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
12145     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
12146     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
12147     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
12148     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
12149     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
12150     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
12151     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
12152     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
12153     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
12154     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
12155     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
12156     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
12157     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
12158     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
12159     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
12160     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
12161     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12162     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
12163     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
12164     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
12165     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
12166     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
12167     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
12168     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
12169     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
12170     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
12171       _codec ("MPEG-2 video");
12172       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
12173           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12174       break;
12175     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
12176       _codec ("GIF still images");
12177       caps = gst_caps_new_empty_simple ("image/gif");
12178       break;
12179     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
12180     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
12181     case GST_MAKE_FOURCC ('s', '2', '6', '3'):
12182     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
12183       _codec ("H.263");
12184       /* ffmpeg uses the height/width props, don't know why */
12185       caps = gst_caps_new_simple ("video/x-h263",
12186           "variant", G_TYPE_STRING, "itu", NULL);
12187       break;
12188     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
12189     case GST_MAKE_FOURCC ('M', 'P', '4', 'V'):
12190       _codec ("MPEG-4 video");
12191       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
12192           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12193       break;
12194     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
12195     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
12196       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
12197       caps = gst_caps_new_simple ("video/x-msmpeg",
12198           "msmpegversion", G_TYPE_INT, 43, NULL);
12199       break;
12200     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
12201       _codec ("DivX 3");
12202       caps = gst_caps_new_simple ("video/x-divx",
12203           "divxversion", G_TYPE_INT, 3, NULL);
12204       break;
12205     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
12206     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
12207       _codec ("DivX 4");
12208       caps = gst_caps_new_simple ("video/x-divx",
12209           "divxversion", G_TYPE_INT, 4, NULL);
12210       break;
12211     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
12212       _codec ("DivX 5");
12213       caps = gst_caps_new_simple ("video/x-divx",
12214           "divxversion", G_TYPE_INT, 5, NULL);
12215       break;
12216
12217     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
12218     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
12219     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
12220     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
12221     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
12222     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
12223       caps = gst_caps_new_simple ("video/mpeg",
12224           "mpegversion", G_TYPE_INT, 4, NULL);
12225       if (codec_name)
12226         *codec_name = g_strdup ("MPEG-4");
12227       break;
12228
12229     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
12230       _codec ("Cinepak");
12231       caps = gst_caps_new_empty_simple ("video/x-cinepak");
12232       break;
12233     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
12234       _codec ("Apple QuickDraw");
12235       caps = gst_caps_new_empty_simple ("video/x-qdrw");
12236       break;
12237     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
12238       _codec ("Apple video");
12239       caps = gst_caps_new_empty_simple ("video/x-apple-video");
12240       break;
12241     case GST_MAKE_FOURCC ('H', '2', '6', '4'):
12242     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
12243       _codec ("H.264 / AVC");
12244       caps = gst_caps_new_simple ("video/x-h264",
12245           "stream-format", G_TYPE_STRING, "avc",
12246           "alignment", G_TYPE_STRING, "au", NULL);
12247       break;
12248     case GST_MAKE_FOURCC ('a', 'v', 'c', '3'):
12249       _codec ("H.264 / AVC");
12250       caps = gst_caps_new_simple ("video/x-h264",
12251           "stream-format", G_TYPE_STRING, "avc3",
12252           "alignment", G_TYPE_STRING, "au", NULL);
12253       break;
12254     case GST_MAKE_FOURCC ('H', '2', '6', '5'):
12255     case GST_MAKE_FOURCC ('h', 'v', 'c', '1'):
12256       _codec ("H.265 / HEVC");
12257       caps = gst_caps_new_simple ("video/x-h265",
12258           "stream-format", G_TYPE_STRING, "hvc1",
12259           "alignment", G_TYPE_STRING, "au", NULL);
12260       break;
12261     case GST_MAKE_FOURCC ('h', 'e', 'v', '1'):
12262       _codec ("H.265 / HEVC");
12263       caps = gst_caps_new_simple ("video/x-h265",
12264           "stream-format", G_TYPE_STRING, "hev1",
12265           "alignment", G_TYPE_STRING, "au", NULL);
12266       break;
12267     case GST_MAKE_FOURCC ('r', 'l', 'e', ' '):
12268       _codec ("Run-length encoding");
12269       caps = gst_caps_new_simple ("video/x-rle",
12270           "layout", G_TYPE_STRING, "quicktime", NULL);
12271       break;
12272     case GST_MAKE_FOURCC ('W', 'R', 'L', 'E'):
12273       _codec ("Run-length encoding");
12274       caps = gst_caps_new_simple ("video/x-rle",
12275           "layout", G_TYPE_STRING, "microsoft", NULL);
12276       break;
12277     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
12278     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
12279       _codec ("Indeo Video 3");
12280       caps = gst_caps_new_simple ("video/x-indeo",
12281           "indeoversion", G_TYPE_INT, 3, NULL);
12282       break;
12283     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
12284     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
12285       _codec ("Intel Video 4");
12286       caps = gst_caps_new_simple ("video/x-indeo",
12287           "indeoversion", G_TYPE_INT, 4, NULL);
12288       break;
12289     case GST_MAKE_FOURCC ('d', 'v', 'c', 'p'):
12290     case GST_MAKE_FOURCC ('d', 'v', 'c', ' '):
12291     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
12292     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
12293     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
12294     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
12295     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
12296     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
12297       _codec ("DV Video");
12298       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
12299           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12300       break;
12301     case GST_MAKE_FOURCC ('d', 'v', '5', 'n'): /* DVCPRO50 NTSC */
12302     case GST_MAKE_FOURCC ('d', 'v', '5', 'p'): /* DVCPRO50 PAL */
12303       _codec ("DVCPro50 Video");
12304       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
12305           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12306       break;
12307     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
12308     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
12309       _codec ("DVCProHD Video");
12310       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
12311           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12312       break;
12313     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
12314       _codec ("Apple Graphics (SMC)");
12315       caps = gst_caps_new_empty_simple ("video/x-smc");
12316       break;
12317     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
12318       _codec ("VP3");
12319       caps = gst_caps_new_empty_simple ("video/x-vp3");
12320       break;
12321     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
12322       _codec ("VP6 Flash");
12323       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
12324       break;
12325     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
12326       _codec ("Theora");
12327       caps = gst_caps_new_empty_simple ("video/x-theora");
12328       /* theora uses one byte of padding in the data stream because it does not
12329        * allow 0 sized packets while theora does */
12330       stream->padding = 1;
12331       break;
12332     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
12333       _codec ("Dirac");
12334       caps = gst_caps_new_empty_simple ("video/x-dirac");
12335       break;
12336     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
12337       _codec ("TIFF still images");
12338       caps = gst_caps_new_empty_simple ("image/tiff");
12339       break;
12340     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
12341       _codec ("Apple Intermediate Codec");
12342       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
12343       break;
12344     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
12345       _codec ("AVID DNxHD");
12346       caps = gst_caps_from_string ("video/x-dnxhd");
12347       break;
12348     case GST_MAKE_FOURCC ('V', 'P', '8', '0'):
12349       _codec ("On2 VP8");
12350       caps = gst_caps_from_string ("video/x-vp8");
12351       break;
12352     case GST_MAKE_FOURCC ('a', 'p', 'c', 's'):
12353       _codec ("Apple ProRes LT");
12354       caps =
12355           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
12356           NULL);
12357       break;
12358     case GST_MAKE_FOURCC ('a', 'p', 'c', 'h'):
12359       _codec ("Apple ProRes HQ");
12360       caps =
12361           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
12362           NULL);
12363       break;
12364     case GST_MAKE_FOURCC ('a', 'p', 'c', 'n'):
12365       _codec ("Apple ProRes");
12366       caps =
12367           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12368           "standard", NULL);
12369       break;
12370     case GST_MAKE_FOURCC ('a', 'p', 'c', 'o'):
12371       _codec ("Apple ProRes Proxy");
12372       caps =
12373           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12374           "proxy", NULL);
12375       break;
12376     case GST_MAKE_FOURCC ('a', 'p', '4', 'h'):
12377       _codec ("Apple ProRes 4444");
12378       caps =
12379           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
12380           "4444", NULL);
12381       break;
12382     case GST_MAKE_FOURCC ('v', 'c', '-', '1'):
12383     case FOURCC_ovc1:
12384       _codec ("VC-1");
12385       caps = gst_caps_new_simple ("video/x-wmv",
12386           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
12387       break;
12388     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
12389     default:
12390     {
12391       char *s, fourstr[5];
12392
12393       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12394       s = g_strdup_printf ("video/x-gst-fourcc-%s", g_strstrip (fourstr));
12395       caps = gst_caps_new_empty_simple (s);
12396       g_free (s);
12397       break;
12398     }
12399   }
12400
12401   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
12402     GstVideoInfo info;
12403
12404     gst_video_info_init (&info);
12405     gst_video_info_set_format (&info, format, stream->width, stream->height);
12406
12407     caps = gst_video_info_to_caps (&info);
12408     *codec_name = gst_pb_utils_get_codec_description (caps);
12409
12410     /* enable clipping for raw video streams */
12411     stream->need_clip = TRUE;
12412   }
12413
12414   return caps;
12415 }
12416
12417 static GstCaps *
12418 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12419     guint32 fourcc, const guint8 * data, int len, gchar ** codec_name)
12420 {
12421   GstCaps *caps;
12422   const GstStructure *s;
12423   const gchar *name;
12424   gint endian = 0;
12425   GstAudioFormat format = 0;
12426   gint depth;
12427
12428   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12429
12430   depth = stream->bytes_per_packet * 8;
12431
12432   switch (fourcc) {
12433     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
12434     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
12435       /* 8-bit audio is unsigned */
12436       if (depth == 8)
12437         format = GST_AUDIO_FORMAT_U8;
12438       /* otherwise it's signed and big-endian just like 'twos' */
12439     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
12440       endian = G_BIG_ENDIAN;
12441       /* fall-through */
12442     case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
12443     {
12444       gchar *str;
12445
12446       if (!endian)
12447         endian = G_LITTLE_ENDIAN;
12448
12449       if (!format)
12450         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
12451
12452       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
12453       _codec (str);
12454       g_free (str);
12455
12456       caps = gst_caps_new_simple ("audio/x-raw",
12457           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12458           "layout", G_TYPE_STRING, "interleaved", NULL);
12459       break;
12460     }
12461     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
12462       _codec ("Raw 64-bit floating-point audio");
12463       caps = gst_caps_new_simple ("audio/x-raw",
12464           "format", G_TYPE_STRING, "F64BE",
12465           "layout", G_TYPE_STRING, "interleaved", NULL);
12466       break;
12467     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
12468       _codec ("Raw 32-bit floating-point audio");
12469       caps = gst_caps_new_simple ("audio/x-raw",
12470           "format", G_TYPE_STRING, "F32BE",
12471           "layout", G_TYPE_STRING, "interleaved", NULL);
12472       break;
12473     case FOURCC_in24:
12474       _codec ("Raw 24-bit PCM audio");
12475       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
12476        * endian later */
12477       caps = gst_caps_new_simple ("audio/x-raw",
12478           "format", G_TYPE_STRING, "S24BE",
12479           "layout", G_TYPE_STRING, "interleaved", NULL);
12480       break;
12481     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
12482       _codec ("Raw 32-bit PCM audio");
12483       caps = gst_caps_new_simple ("audio/x-raw",
12484           "format", G_TYPE_STRING, "S32BE",
12485           "layout", G_TYPE_STRING, "interleaved", NULL);
12486       break;
12487     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
12488       _codec ("Mu-law audio");
12489       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
12490       break;
12491     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
12492       _codec ("A-law audio");
12493       caps = gst_caps_new_empty_simple ("audio/x-alaw");
12494       break;
12495     case 0x0200736d:
12496     case 0x6d730002:
12497       _codec ("Microsoft ADPCM");
12498       /* Microsoft ADPCM-ACM code 2 */
12499       caps = gst_caps_new_simple ("audio/x-adpcm",
12500           "layout", G_TYPE_STRING, "microsoft", NULL);
12501       break;
12502     case 0x1100736d:
12503     case 0x6d730011:
12504       _codec ("DVI/IMA ADPCM");
12505       caps = gst_caps_new_simple ("audio/x-adpcm",
12506           "layout", G_TYPE_STRING, "dvi", NULL);
12507       break;
12508     case 0x1700736d:
12509     case 0x6d730017:
12510       _codec ("DVI/Intel IMA ADPCM");
12511       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
12512       caps = gst_caps_new_simple ("audio/x-adpcm",
12513           "layout", G_TYPE_STRING, "quicktime", NULL);
12514       break;
12515     case 0x5500736d:
12516     case 0x6d730055:
12517       /* MPEG layer 3, CBR only (pre QT4.1) */
12518     case GST_MAKE_FOURCC ('.', 'm', 'p', '3'):
12519       _codec ("MPEG-1 layer 3");
12520       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
12521       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
12522           "mpegversion", G_TYPE_INT, 1, NULL);
12523       break;
12524     case 0x20736d:
12525     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
12526       _codec ("EAC-3 audio");
12527       caps = gst_caps_new_simple ("audio/x-eac3",
12528           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12529       stream->sampled = TRUE;
12530       break;
12531     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
12532     case GST_MAKE_FOURCC ('a', 'c', '-', '3'):
12533       _codec ("AC-3 audio");
12534       caps = gst_caps_new_simple ("audio/x-ac3",
12535           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12536       stream->sampled = TRUE;
12537       break;
12538     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
12539     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
12540       _codec ("DTS audio");
12541       caps = gst_caps_new_simple ("audio/x-dts",
12542           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12543       stream->sampled = TRUE;
12544       break;
12545     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
12546     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
12547       _codec ("DTS-HD audio");
12548       caps = gst_caps_new_simple ("audio/x-dts",
12549           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
12550       stream->sampled = TRUE;
12551       break;
12552     case GST_MAKE_FOURCC ('M', 'A', 'C', '3'):
12553       _codec ("MACE-3");
12554       caps = gst_caps_new_simple ("audio/x-mace",
12555           "maceversion", G_TYPE_INT, 3, NULL);
12556       break;
12557     case GST_MAKE_FOURCC ('M', 'A', 'C', '6'):
12558       _codec ("MACE-6");
12559       caps = gst_caps_new_simple ("audio/x-mace",
12560           "maceversion", G_TYPE_INT, 6, NULL);
12561       break;
12562     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
12563       /* ogg/vorbis */
12564       caps = gst_caps_new_empty_simple ("application/ogg");
12565       break;
12566     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
12567       _codec ("DV audio");
12568       caps = gst_caps_new_empty_simple ("audio/x-dv");
12569       break;
12570     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
12571       _codec ("MPEG-4 AAC audio");
12572       caps = gst_caps_new_simple ("audio/mpeg",
12573           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
12574           "stream-format", G_TYPE_STRING, "raw", NULL);
12575       break;
12576     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
12577       _codec ("QDesign Music");
12578       caps = gst_caps_new_empty_simple ("audio/x-qdm");
12579       break;
12580     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
12581       _codec ("QDesign Music v.2");
12582       /* FIXME: QDesign music version 2 (no constant) */
12583       if (FALSE && data) {
12584         caps = gst_caps_new_simple ("audio/x-qdm2",
12585             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
12586             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
12587             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
12588       } else {
12589         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
12590       }
12591       break;
12592     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
12593       _codec ("GSM audio");
12594       caps = gst_caps_new_empty_simple ("audio/x-gsm");
12595       break;
12596     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
12597       _codec ("AMR audio");
12598       caps = gst_caps_new_empty_simple ("audio/AMR");
12599       break;
12600     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
12601       _codec ("AMR-WB audio");
12602       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
12603       break;
12604     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
12605       _codec ("Quicktime IMA ADPCM");
12606       caps = gst_caps_new_simple ("audio/x-adpcm",
12607           "layout", G_TYPE_STRING, "quicktime", NULL);
12608       break;
12609     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
12610       _codec ("Apple lossless audio");
12611       caps = gst_caps_new_empty_simple ("audio/x-alac");
12612       break;
12613     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
12614       _codec ("QualComm PureVoice");
12615       caps = gst_caps_from_string ("audio/qcelp");
12616       break;
12617     case GST_MAKE_FOURCC ('w', 'm', 'a', ' '):
12618     case FOURCC_owma:
12619       _codec ("WMA");
12620       caps = gst_caps_new_empty_simple ("audio/x-wma");
12621       break;
12622     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
12623     {
12624       guint32 flags = 0;
12625       guint32 depth = 0;
12626       guint32 width = 0;
12627       GstAudioFormat format;
12628       enum
12629       {
12630         FLAG_IS_FLOAT = 0x1,
12631         FLAG_IS_BIG_ENDIAN = 0x2,
12632         FLAG_IS_SIGNED = 0x4,
12633         FLAG_IS_PACKED = 0x8,
12634         FLAG_IS_ALIGNED_HIGH = 0x10,
12635         FLAG_IS_NON_INTERLEAVED = 0x20
12636       };
12637       _codec ("Raw LPCM audio");
12638
12639       if (data && len >= 56) {
12640         depth = QT_UINT32 (data + 40);
12641         flags = QT_UINT32 (data + 44);
12642         width = QT_UINT32 (data + 48) * 8 / stream->n_channels;
12643       }
12644       if ((flags & FLAG_IS_FLOAT) == 0) {
12645         if (depth == 0)
12646           depth = 16;
12647         if (width == 0)
12648           width = 16;
12649         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
12650             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
12651             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
12652         caps = gst_caps_new_simple ("audio/x-raw",
12653             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12654             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12655             "non-interleaved" : "interleaved", NULL);
12656       } else {
12657         if (width == 0)
12658           width = 32;
12659         if (width == 64) {
12660           if (flags & FLAG_IS_BIG_ENDIAN)
12661             format = GST_AUDIO_FORMAT_F64BE;
12662           else
12663             format = GST_AUDIO_FORMAT_F64LE;
12664         } else {
12665           if (flags & FLAG_IS_BIG_ENDIAN)
12666             format = GST_AUDIO_FORMAT_F32BE;
12667           else
12668             format = GST_AUDIO_FORMAT_F32LE;
12669         }
12670         caps = gst_caps_new_simple ("audio/x-raw",
12671             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
12672             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
12673             "non-interleaved" : "interleaved", NULL);
12674       }
12675       break;
12676     }
12677     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
12678       /* ? */
12679     default:
12680     {
12681       char *s, fourstr[5];
12682
12683       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12684       s = g_strdup_printf ("audio/x-gst-fourcc-%s", g_strstrip (fourstr));
12685       caps = gst_caps_new_empty_simple (s);
12686       g_free (s);
12687       break;
12688     }
12689   }
12690
12691   if (caps) {
12692     GstCaps *templ_caps =
12693         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
12694     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
12695     gst_caps_unref (caps);
12696     gst_caps_unref (templ_caps);
12697     caps = intersection;
12698   }
12699
12700   /* enable clipping for raw audio streams */
12701   s = gst_caps_get_structure (caps, 0);
12702   name = gst_structure_get_name (s);
12703   if (g_str_has_prefix (name, "audio/x-raw")) {
12704     stream->need_clip = TRUE;
12705     stream->max_buffer_size = 4096 * stream->bytes_per_frame;
12706     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
12707   }
12708   return caps;
12709 }
12710
12711 static GstCaps *
12712 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12713     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12714 {
12715   GstCaps *caps;
12716
12717   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
12718
12719   switch (fourcc) {
12720     case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
12721       _codec ("DVD subtitle");
12722       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
12723       stream->need_process = TRUE;
12724       break;
12725     case GST_MAKE_FOURCC ('t', 'e', 'x', 't'):
12726       _codec ("Quicktime timed text");
12727       goto text;
12728     case GST_MAKE_FOURCC ('t', 'x', '3', 'g'):
12729       _codec ("3GPP timed text");
12730     text:
12731       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
12732           "utf8", NULL);
12733       /* actual text piece needs to be extracted */
12734       stream->need_process = TRUE;
12735       break;
12736     default:
12737     {
12738       char *s, fourstr[5];
12739
12740       g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12741       s = g_strdup_printf ("text/x-gst-fourcc-%s", g_strstrip (fourstr));
12742       caps = gst_caps_new_empty_simple (s);
12743       g_free (s);
12744       break;
12745     }
12746   }
12747   return caps;
12748 }
12749
12750 static GstCaps *
12751 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
12752     guint32 fourcc, const guint8 * stsd_data, gchar ** codec_name)
12753 {
12754   GstCaps *caps;
12755
12756   switch (fourcc) {
12757     case GST_MAKE_FOURCC ('m', '1', 'v', ' '):
12758       _codec ("MPEG 1 video");
12759       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
12760           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
12761       break;
12762     default:
12763       caps = NULL;
12764       break;
12765   }
12766   return caps;
12767 }
12768
12769 static void
12770 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
12771     const gchar * system_id)
12772 {
12773   gint i;
12774
12775   if (!qtdemux->protection_system_ids)
12776     qtdemux->protection_system_ids =
12777         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
12778   /* Check whether we already have an entry for this system ID. */
12779   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
12780     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
12781     if (g_ascii_strcasecmp (system_id, id) == 0) {
12782       return;
12783     }
12784   }
12785   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
12786   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
12787           -1));
12788 }