qtdemux: Fix cenc-related leaks
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib/gi18n-lib.h>
54
55 #include <glib/gprintf.h>
56 #include <gst/base/base.h>
57 #include <gst/tag/tag.h>
58 #include <gst/audio/audio.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 static GstStaticPadTemplate gst_qtdemux_metasrc_template =
293 GST_STATIC_PAD_TEMPLATE ("meta_%u",
294     GST_PAD_SRC,
295     GST_PAD_SOMETIMES,
296     GST_STATIC_CAPS_ANY);
297
298 #define gst_qtdemux_parent_class parent_class
299 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
300 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
301     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
302
303 static void gst_qtdemux_dispose (GObject * object);
304 static void gst_qtdemux_finalize (GObject * object);
305
306 static guint32
307 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
308     GstClockTime media_time);
309 static guint32
310 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
311     QtDemuxStream * str, gint64 media_offset);
312
313 #if 0
314 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
315 static GstIndex *gst_qtdemux_get_index (GstElement * element);
316 #endif
317 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
318     GstStateChange transition);
319 static void gst_qtdemux_set_context (GstElement * element,
320     GstContext * context);
321 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
322 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
323     GstObject * parent, GstPadMode mode, gboolean active);
324
325 static void gst_qtdemux_loop (GstPad * pad);
326 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
327     GstBuffer * inbuf);
328 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
329     GstEvent * event);
330 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
331     GstQuery * query);
332 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
333 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
334     QtDemuxStream * stream);
335 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
336     QtDemuxStream * stream);
337 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
338     gboolean force);
339
340 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
341
342 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
343     const guint8 * buffer, guint length);
344 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
345     const guint8 * buffer, guint length);
346 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
347
348 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
350     GstTagList * list);
351 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
352     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
353     const guint8 * stsd_entry_data, gchar ** codec_name);
354 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * data, int len, gchar ** codec_name);
357 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
358     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
359     gchar ** codec_name);
360 static GstCaps *qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
361     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
362     gchar ** codec_name);
363 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
364     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
365     const guint8 * stsd_entry_data, gchar ** codec_name);
366
367 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 n);
369 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
370 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
371 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
372 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
373 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
374 static void qtdemux_do_allocation (QtDemuxStream * stream,
375     GstQTDemux * qtdemux);
376 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
377     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
378 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
379     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
380     GstClockTime * _start, GstClockTime * _stop);
381 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
382     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
383
384 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
385 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
386
387 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
388
389 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
390     QtDemuxStream * stream, guint sample_index);
391 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
392     const gchar * id);
393 static void qtdemux_gst_structure_free (GstStructure * gststructure);
394 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
395
396 static void
397 gst_qtdemux_class_init (GstQTDemuxClass * klass)
398 {
399   GObjectClass *gobject_class;
400   GstElementClass *gstelement_class;
401
402   gobject_class = (GObjectClass *) klass;
403   gstelement_class = (GstElementClass *) klass;
404
405   parent_class = g_type_class_peek_parent (klass);
406
407   gobject_class->dispose = gst_qtdemux_dispose;
408   gobject_class->finalize = gst_qtdemux_finalize;
409
410   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
411 #if 0
412   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
413   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
414 #endif
415   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
416
417   gst_tag_register_musicbrainz_tags ();
418
419   gst_element_class_add_static_pad_template (gstelement_class,
420       &gst_qtdemux_sink_template);
421   gst_element_class_add_static_pad_template (gstelement_class,
422       &gst_qtdemux_videosrc_template);
423   gst_element_class_add_static_pad_template (gstelement_class,
424       &gst_qtdemux_audiosrc_template);
425   gst_element_class_add_static_pad_template (gstelement_class,
426       &gst_qtdemux_subsrc_template);
427   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
428       "Codec/Demuxer",
429       "Demultiplex a QuickTime file into audio and video streams",
430       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
431
432   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
433   gst_riff_init ();
434 }
435
436 static void
437 gst_qtdemux_init (GstQTDemux * qtdemux)
438 {
439   qtdemux->sinkpad =
440       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
441   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
442   gst_pad_set_activatemode_function (qtdemux->sinkpad,
443       qtdemux_sink_activate_mode);
444   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
445   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
446   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
447   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
448
449   qtdemux->adapter = gst_adapter_new ();
450   g_queue_init (&qtdemux->protection_event_queue);
451   qtdemux->flowcombiner = gst_flow_combiner_new ();
452   g_mutex_init (&qtdemux->expose_lock);
453
454   qtdemux->active_streams = g_ptr_array_new_with_free_func
455       ((GDestroyNotify) gst_qtdemux_stream_unref);
456   qtdemux->old_streams = g_ptr_array_new_with_free_func
457       ((GDestroyNotify) gst_qtdemux_stream_unref);
458
459   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
460
461   gst_qtdemux_reset (qtdemux, TRUE);
462 }
463
464 static void
465 gst_qtdemux_finalize (GObject * object)
466 {
467   GstQTDemux *qtdemux = GST_QTDEMUX (object);
468
469   g_free (qtdemux->redirect_location);
470
471   G_OBJECT_CLASS (parent_class)->finalize (object);
472 }
473
474 static void
475 gst_qtdemux_dispose (GObject * object)
476 {
477   GstQTDemux *qtdemux = GST_QTDEMUX (object);
478
479   if (qtdemux->adapter) {
480     g_object_unref (G_OBJECT (qtdemux->adapter));
481     qtdemux->adapter = NULL;
482   }
483   gst_tag_list_unref (qtdemux->tag_list);
484   gst_flow_combiner_free (qtdemux->flowcombiner);
485   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
486       NULL);
487   g_queue_clear (&qtdemux->protection_event_queue);
488
489   g_free (qtdemux->cenc_aux_info_sizes);
490   qtdemux->cenc_aux_info_sizes = NULL;
491   g_mutex_clear (&qtdemux->expose_lock);
492
493   g_ptr_array_free (qtdemux->active_streams, TRUE);
494   g_ptr_array_free (qtdemux->old_streams, TRUE);
495
496   G_OBJECT_CLASS (parent_class)->dispose (object);
497 }
498
499 static void
500 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
501 {
502   if (qtdemux->redirect_location) {
503     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
504         (_("This file contains no playable streams.")),
505         ("no known streams found, a redirect message has been posted"),
506         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
507   } else {
508     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
509         (_("This file contains no playable streams.")),
510         ("no known streams found"));
511   }
512 }
513
514 static GstBuffer *
515 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
516 {
517   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
518       mem, size, 0, size, mem, free_func);
519 }
520
521 static GstFlowReturn
522 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
523     GstBuffer ** buf)
524 {
525   GstFlowReturn flow;
526   GstMapInfo map;
527   gsize bsize;
528
529   if (G_UNLIKELY (size == 0)) {
530     GstFlowReturn ret;
531     GstBuffer *tmp = NULL;
532
533     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
534     if (ret != GST_FLOW_OK)
535       return ret;
536
537     gst_buffer_map (tmp, &map, GST_MAP_READ);
538     size = QT_UINT32 (map.data);
539     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
540
541     gst_buffer_unmap (tmp, &map);
542     gst_buffer_unref (tmp);
543   }
544
545   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
546   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
547     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
548       /* we're pulling header but already got most interesting bits,
549        * so never mind the rest (e.g. tags) (that much) */
550       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
551           size);
552       return GST_FLOW_EOS;
553     } else {
554       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
555           (_("This file is invalid and cannot be played.")),
556           ("atom has bogus size %" G_GUINT64_FORMAT, size));
557       return GST_FLOW_ERROR;
558     }
559   }
560
561   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
562
563   if (G_UNLIKELY (flow != GST_FLOW_OK))
564     return flow;
565
566   bsize = gst_buffer_get_size (*buf);
567   /* Catch short reads - we don't want any partial atoms */
568   if (G_UNLIKELY (bsize < size)) {
569     GST_WARNING_OBJECT (qtdemux,
570         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
571     gst_buffer_unref (*buf);
572     *buf = NULL;
573     return GST_FLOW_EOS;
574   }
575
576   return flow;
577 }
578
579 #if 1
580 static gboolean
581 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
582     GstFormat src_format, gint64 src_value, GstFormat dest_format,
583     gint64 * dest_value)
584 {
585   gboolean res = TRUE;
586   QtDemuxStream *stream = gst_pad_get_element_private (pad);
587   gint32 index;
588
589   if (stream->subtype != FOURCC_vide) {
590     res = FALSE;
591     goto done;
592   }
593
594   switch (src_format) {
595     case GST_FORMAT_TIME:
596       switch (dest_format) {
597         case GST_FORMAT_BYTES:{
598           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
599           if (-1 == index) {
600             res = FALSE;
601             goto done;
602           }
603
604           *dest_value = stream->samples[index].offset;
605
606           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
607               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
608               GST_TIME_ARGS (src_value), *dest_value);
609           break;
610         }
611         default:
612           res = FALSE;
613           break;
614       }
615       break;
616     case GST_FORMAT_BYTES:
617       switch (dest_format) {
618         case GST_FORMAT_TIME:{
619           index =
620               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
621               stream, src_value);
622
623           if (-1 == index) {
624             res = FALSE;
625             goto done;
626           }
627
628           *dest_value =
629               QTSTREAMTIME_TO_GSTTIME (stream,
630               stream->samples[index].timestamp);
631           GST_DEBUG_OBJECT (qtdemux,
632               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
633               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
634           break;
635         }
636         default:
637           res = FALSE;
638           break;
639       }
640       break;
641     default:
642       res = FALSE;
643       break;
644   }
645
646 done:
647   return res;
648 }
649 #endif
650
651 static gboolean
652 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
653 {
654   gboolean res = FALSE;
655
656   *duration = GST_CLOCK_TIME_NONE;
657
658   if (qtdemux->duration != 0 &&
659       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
660     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
661     res = TRUE;
662   } else {
663     *duration = GST_CLOCK_TIME_NONE;
664   }
665
666   return res;
667 }
668
669 static gboolean
670 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
671     GstQuery * query)
672 {
673   gboolean res = FALSE;
674   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
675
676   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
677
678   switch (GST_QUERY_TYPE (query)) {
679     case GST_QUERY_POSITION:{
680       GstFormat fmt;
681
682       gst_query_parse_position (query, &fmt, NULL);
683       if (fmt == GST_FORMAT_TIME
684           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
685         gst_query_set_position (query, GST_FORMAT_TIME,
686             qtdemux->segment.position);
687         res = TRUE;
688       }
689     }
690       break;
691     case GST_QUERY_DURATION:{
692       GstFormat fmt;
693
694       gst_query_parse_duration (query, &fmt, NULL);
695       if (fmt == GST_FORMAT_TIME) {
696         /* First try to query upstream */
697         res = gst_pad_query_default (pad, parent, query);
698         if (!res) {
699           GstClockTime duration;
700           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
701             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
702             res = TRUE;
703           }
704         }
705       }
706       break;
707     }
708     case GST_QUERY_CONVERT:{
709       GstFormat src_fmt, dest_fmt;
710       gint64 src_value, dest_value = 0;
711
712       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
713
714       res = gst_qtdemux_src_convert (qtdemux, pad,
715           src_fmt, src_value, dest_fmt, &dest_value);
716       if (res)
717         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
718
719       break;
720     }
721     case GST_QUERY_FORMATS:
722       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
723       res = TRUE;
724       break;
725     case GST_QUERY_SEEKING:{
726       GstFormat fmt;
727       gboolean seekable;
728
729       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
730
731       if (fmt == GST_FORMAT_BYTES) {
732         /* We always refuse BYTES seeks from downstream */
733         break;
734       }
735
736       /* try upstream first */
737       res = gst_pad_query_default (pad, parent, query);
738
739       if (!res) {
740         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
741         if (fmt == GST_FORMAT_TIME) {
742           GstClockTime duration;
743
744           gst_qtdemux_get_duration (qtdemux, &duration);
745           seekable = TRUE;
746           if (!qtdemux->pullbased) {
747             GstQuery *q;
748
749             /* we might be able with help from upstream */
750             seekable = FALSE;
751             q = gst_query_new_seeking (GST_FORMAT_BYTES);
752             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
753               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
754               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
755             }
756             gst_query_unref (q);
757           }
758           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
759           res = TRUE;
760         }
761       }
762       break;
763     }
764     case GST_QUERY_SEGMENT:
765     {
766       GstFormat format;
767       gint64 start, stop;
768
769       format = qtdemux->segment.format;
770
771       start =
772           gst_segment_to_stream_time (&qtdemux->segment, format,
773           qtdemux->segment.start);
774       if ((stop = qtdemux->segment.stop) == -1)
775         stop = qtdemux->segment.duration;
776       else
777         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
778
779       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
780       res = TRUE;
781       break;
782     }
783     default:
784       res = gst_pad_query_default (pad, parent, query);
785       break;
786   }
787
788   return res;
789 }
790
791 static void
792 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
793 {
794   if (G_LIKELY (stream->pad)) {
795     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
796         GST_DEBUG_PAD_NAME (stream->pad));
797
798     if (!gst_tag_list_is_empty (stream->stream_tags)) {
799       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
800           stream->stream_tags);
801       gst_pad_push_event (stream->pad,
802           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
803     }
804
805     if (G_UNLIKELY (stream->send_global_tags)) {
806       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
807           qtdemux->tag_list);
808       gst_pad_push_event (stream->pad,
809           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
810       stream->send_global_tags = FALSE;
811     }
812   }
813 }
814
815 /* push event on all source pads; takes ownership of the event */
816 static void
817 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
818 {
819   gboolean has_valid_stream = FALSE;
820   GstEventType etype = GST_EVENT_TYPE (event);
821   guint i;
822
823   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
824       GST_EVENT_TYPE_NAME (event));
825
826   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
827     GstPad *pad;
828     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
829     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
830
831     if ((pad = stream->pad)) {
832       has_valid_stream = TRUE;
833
834       if (etype == GST_EVENT_EOS) {
835         /* let's not send twice */
836         if (stream->sent_eos)
837           continue;
838         stream->sent_eos = TRUE;
839       }
840
841       gst_pad_push_event (pad, gst_event_ref (event));
842     }
843   }
844
845   gst_event_unref (event);
846
847   /* if it is EOS and there are no pads, post an error */
848   if (!has_valid_stream && etype == GST_EVENT_EOS) {
849     gst_qtdemux_post_no_playable_stream_error (qtdemux);
850   }
851 }
852
853 typedef struct
854 {
855   guint64 media_time;
856 } FindData;
857
858 static gint
859 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
860 {
861   if ((gint64) s1->timestamp > *media_time)
862     return 1;
863   if ((gint64) s1->timestamp == *media_time)
864     return 0;
865
866   return -1;
867 }
868
869 /* find the index of the sample that includes the data for @media_time using a
870  * binary search.  Only to be called in optimized cases of linear search below.
871  *
872  * Returns the index of the sample with the corresponding *DTS*.
873  */
874 static guint32
875 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
876     guint64 media_time)
877 {
878   QtDemuxSample *result;
879   guint32 index;
880
881   /* convert media_time to mov format */
882   media_time =
883       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
884
885   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
886       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
887       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
888
889   if (G_LIKELY (result))
890     index = result - str->samples;
891   else
892     index = 0;
893
894   return index;
895 }
896
897
898
899 /* find the index of the sample that includes the data for @media_offset using a
900  * linear search
901  *
902  * Returns the index of the sample.
903  */
904 static guint32
905 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
906     QtDemuxStream * str, gint64 media_offset)
907 {
908   QtDemuxSample *result = str->samples;
909   guint32 index = 0;
910
911   if (result == NULL || str->n_samples == 0)
912     return -1;
913
914   if (media_offset == result->offset)
915     return index;
916
917   result++;
918   while (index < str->n_samples - 1) {
919     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
920       goto parse_failed;
921
922     if (media_offset < result->offset)
923       break;
924
925     index++;
926     result++;
927   }
928   return index;
929
930   /* ERRORS */
931 parse_failed:
932   {
933     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
934     return -1;
935   }
936 }
937
938 /* find the index of the sample that includes the data for @media_time using a
939  * linear search, and keeping in mind that not all samples may have been parsed
940  * yet.  If possible, it will delegate to binary search.
941  *
942  * Returns the index of the sample.
943  */
944 static guint32
945 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
946     GstClockTime media_time)
947 {
948   guint32 index = 0;
949   guint64 mov_time;
950   QtDemuxSample *sample;
951
952   /* convert media_time to mov format */
953   mov_time =
954       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
955
956   sample = str->samples;
957   if (mov_time == sample->timestamp + sample->pts_offset)
958     return index;
959
960   /* use faster search if requested time in already parsed range */
961   sample = str->samples + str->stbl_index;
962   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
963     index = gst_qtdemux_find_index (qtdemux, str, media_time);
964     sample = str->samples + index;
965   } else {
966     while (index < str->n_samples - 1) {
967       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
968         goto parse_failed;
969
970       sample = str->samples + index + 1;
971       if (mov_time < sample->timestamp) {
972         sample = str->samples + index;
973         break;
974       }
975
976       index++;
977     }
978   }
979
980   /* sample->timestamp is now <= media_time, need to find the corresponding
981    * PTS now by looking backwards */
982   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
983     index--;
984     sample = str->samples + index;
985   }
986
987   return index;
988
989   /* ERRORS */
990 parse_failed:
991   {
992     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
993     return -1;
994   }
995 }
996
997 /* find the index of the keyframe needed to decode the sample at @index
998  * of stream @str, or of a subsequent keyframe (depending on @next)
999  *
1000  * Returns the index of the keyframe.
1001  */
1002 static guint32
1003 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1004     guint32 index, gboolean next)
1005 {
1006   guint32 new_index = index;
1007
1008   if (index >= str->n_samples) {
1009     new_index = str->n_samples;
1010     goto beach;
1011   }
1012
1013   /* all keyframes, return index */
1014   if (str->all_keyframe) {
1015     new_index = index;
1016     goto beach;
1017   }
1018
1019   /* else search until we have a keyframe */
1020   while (new_index < str->n_samples) {
1021     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1022       goto parse_failed;
1023
1024     if (str->samples[new_index].keyframe)
1025       break;
1026
1027     if (new_index == 0)
1028       break;
1029
1030     if (next)
1031       new_index++;
1032     else
1033       new_index--;
1034   }
1035
1036   if (new_index == str->n_samples) {
1037     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1038     new_index = -1;
1039   }
1040
1041 beach:
1042   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1043       "gave %u", next ? "after" : "before", index, new_index);
1044
1045   return new_index;
1046
1047   /* ERRORS */
1048 parse_failed:
1049   {
1050     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1051     return -1;
1052   }
1053 }
1054
1055 /* find the segment for @time_position for @stream
1056  *
1057  * Returns the index of the segment containing @time_position.
1058  * Returns the last segment and sets the @eos variable to TRUE
1059  * if the time is beyond the end. @eos may be NULL
1060  */
1061 static guint32
1062 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1063     GstClockTime time_position)
1064 {
1065   gint i;
1066   guint32 seg_idx;
1067
1068   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1069       GST_TIME_ARGS (time_position));
1070
1071   seg_idx = -1;
1072   for (i = 0; i < stream->n_segments; i++) {
1073     QtDemuxSegment *segment = &stream->segments[i];
1074
1075     GST_LOG_OBJECT (stream->pad,
1076         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1077         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1078
1079     /* For the last segment we include stop_time in the last segment */
1080     if (i < stream->n_segments - 1) {
1081       if (segment->time <= time_position && time_position < segment->stop_time) {
1082         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1083         seg_idx = i;
1084         break;
1085       }
1086     } else {
1087       /* Last segment always matches */
1088       seg_idx = i;
1089       break;
1090     }
1091   }
1092   return seg_idx;
1093 }
1094
1095 /* move the stream @str to the sample position @index.
1096  *
1097  * Updates @str->sample_index and marks discontinuity if needed.
1098  */
1099 static void
1100 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1101     guint32 index)
1102 {
1103   /* no change needed */
1104   if (index == str->sample_index)
1105     return;
1106
1107   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1108       str->n_samples);
1109
1110   /* position changed, we have a discont */
1111   str->sample_index = index;
1112   str->offset_in_sample = 0;
1113   /* Each time we move in the stream we store the position where we are
1114    * starting from */
1115   str->from_sample = index;
1116   str->discont = TRUE;
1117 }
1118
1119 static void
1120 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1121     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1122 {
1123   guint64 min_offset;
1124   gint64 min_byte_offset = -1;
1125   guint i;
1126
1127   min_offset = desired_time;
1128
1129   /* for each stream, find the index of the sample in the segment
1130    * and move back to the previous keyframe. */
1131   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1132     QtDemuxStream *str;
1133     guint32 index, kindex;
1134     guint32 seg_idx;
1135     GstClockTime media_start;
1136     GstClockTime media_time;
1137     GstClockTime seg_time;
1138     QtDemuxSegment *seg;
1139     gboolean empty_segment = FALSE;
1140
1141     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1142
1143     if (CUR_STREAM (str)->sparse && !use_sparse)
1144       continue;
1145
1146     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1147     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1148
1149     /* get segment and time in the segment */
1150     seg = &str->segments[seg_idx];
1151     seg_time = (desired_time - seg->time) * seg->rate;
1152
1153     while (QTSEGMENT_IS_EMPTY (seg)) {
1154       seg_time = 0;
1155       empty_segment = TRUE;
1156       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1157           seg_idx);
1158       seg_idx++;
1159       if (seg_idx == str->n_segments)
1160         break;
1161       seg = &str->segments[seg_idx];
1162     }
1163
1164     if (seg_idx == str->n_segments) {
1165       /* FIXME track shouldn't have the last segment as empty, but if it
1166        * happens we better handle it */
1167       continue;
1168     }
1169
1170     /* get the media time in the segment */
1171     media_start = seg->media_start + seg_time;
1172
1173     /* get the index of the sample with media time */
1174     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1175     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1176         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1177         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1178         empty_segment);
1179
1180     /* shift to next frame if we are looking for next keyframe */
1181     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1182         && index < str->stbl_index)
1183       index++;
1184
1185     if (!empty_segment) {
1186       /* find previous keyframe */
1187       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1188
1189       /* we will settle for one before if none found after */
1190       if (next && kindex == -1)
1191         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1192
1193       /* Update the requested time whenever a keyframe was found, to make it
1194        * accurate and avoid having the first buffer fall outside of the segment
1195        */
1196       if (kindex != -1) {
1197         index = kindex;
1198
1199         /* get timestamp of keyframe */
1200         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1201         GST_DEBUG_OBJECT (qtdemux,
1202             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1203             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1204             str->samples[kindex].offset);
1205
1206         /* keyframes in the segment get a chance to change the
1207          * desired_offset. keyframes out of the segment are
1208          * ignored. */
1209         if (media_time >= seg->media_start) {
1210           GstClockTime seg_time;
1211
1212           /* this keyframe is inside the segment, convert back to
1213            * segment time */
1214           seg_time = (media_time - seg->media_start) + seg->time;
1215           if ((!next && (seg_time < min_offset)) ||
1216               (next && (seg_time > min_offset)))
1217             min_offset = seg_time;
1218         }
1219       }
1220     }
1221
1222     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1223       min_byte_offset = str->samples[index].offset;
1224   }
1225
1226   if (key_time)
1227     *key_time = min_offset;
1228   if (key_offset)
1229     *key_offset = min_byte_offset;
1230 }
1231
1232 static gboolean
1233 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1234     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1235 {
1236   gboolean res;
1237
1238   g_return_val_if_fail (format != NULL, FALSE);
1239   g_return_val_if_fail (cur != NULL, FALSE);
1240   g_return_val_if_fail (stop != NULL, FALSE);
1241
1242   if (*format == GST_FORMAT_TIME)
1243     return TRUE;
1244
1245   res = TRUE;
1246   if (cur_type != GST_SEEK_TYPE_NONE)
1247     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1248   if (res && stop_type != GST_SEEK_TYPE_NONE)
1249     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1250
1251   if (res)
1252     *format = GST_FORMAT_TIME;
1253
1254   return res;
1255 }
1256
1257 /* perform seek in push based mode:
1258    find BYTE position to move to based on time and delegate to upstream
1259 */
1260 static gboolean
1261 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1262 {
1263   gdouble rate;
1264   GstFormat format;
1265   GstSeekFlags flags;
1266   GstSeekType cur_type, stop_type;
1267   gint64 cur, stop, key_cur;
1268   gboolean res;
1269   gint64 byte_cur;
1270   gint64 original_stop;
1271   guint32 seqnum;
1272
1273   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1274
1275   gst_event_parse_seek (event, &rate, &format, &flags,
1276       &cur_type, &cur, &stop_type, &stop);
1277   seqnum = gst_event_get_seqnum (event);
1278
1279   /* Directly send the instant-rate-change event here before taking the
1280    * stream-lock so that it can be applied as soon as possible */
1281   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1282     GstEvent *ev;
1283
1284     /* instant rate change only supported if direction does not change. All
1285      * other requirements are already checked before creating the seek event
1286      * but let's double-check here to be sure */
1287     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1288         (qtdemux->segment.rate < 0 && rate > 0) ||
1289         cur_type != GST_SEEK_TYPE_NONE ||
1290         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1291       GST_ERROR_OBJECT (qtdemux,
1292           "Instant rate change seeks only supported in the "
1293           "same direction, without flushing and position change");
1294       return FALSE;
1295     }
1296
1297     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1298         (GstSegmentFlags) flags);
1299     gst_event_set_seqnum (ev, seqnum);
1300     gst_qtdemux_push_event (qtdemux, ev);
1301     return TRUE;
1302   }
1303
1304   /* only forward streaming and seeking is possible */
1305   if (rate <= 0)
1306     goto unsupported_seek;
1307
1308   /* convert to TIME if needed and possible */
1309   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1310           stop_type, &stop))
1311     goto no_format;
1312
1313   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1314    * the original stop position to use when upstream pushes the new segment
1315    * for this seek */
1316   original_stop = stop;
1317   stop = -1;
1318
1319   /* find reasonable corresponding BYTE position,
1320    * also try to mind about keyframes, since we can not go back a bit for them
1321    * later on */
1322   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1323    * mostly just work, but let's not yet boldly go there  ... */
1324   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1325
1326   if (byte_cur == -1)
1327     goto abort_seek;
1328
1329   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1330       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1331       stop);
1332
1333   GST_OBJECT_LOCK (qtdemux);
1334   qtdemux->seek_offset = byte_cur;
1335   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1336     qtdemux->push_seek_start = cur;
1337   } else {
1338     qtdemux->push_seek_start = key_cur;
1339   }
1340
1341   if (stop_type == GST_SEEK_TYPE_NONE) {
1342     qtdemux->push_seek_stop = qtdemux->segment.stop;
1343   } else {
1344     qtdemux->push_seek_stop = original_stop;
1345   }
1346   GST_OBJECT_UNLOCK (qtdemux);
1347
1348   qtdemux->segment_seqnum = seqnum;
1349   /* BYTE seek event */
1350   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1351       stop_type, stop);
1352   gst_event_set_seqnum (event, seqnum);
1353   res = gst_pad_push_event (qtdemux->sinkpad, event);
1354
1355   return res;
1356
1357   /* ERRORS */
1358 abort_seek:
1359   {
1360     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1361         "seek aborted.");
1362     return FALSE;
1363   }
1364 unsupported_seek:
1365   {
1366     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1367     return FALSE;
1368   }
1369 no_format:
1370   {
1371     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1372     return FALSE;
1373   }
1374 }
1375
1376 /* perform the seek.
1377  *
1378  * We set all segment_indexes in the streams to unknown and
1379  * adjust the time_position to the desired position. this is enough
1380  * to trigger a segment switch in the streaming thread to start
1381  * streaming from the desired position.
1382  *
1383  * Keyframe seeking is a little more complicated when dealing with
1384  * segments. Ideally we want to move to the previous keyframe in
1385  * the segment but there might not be a keyframe in the segment. In
1386  * fact, none of the segments could contain a keyframe. We take a
1387  * practical approach: seek to the previous keyframe in the segment,
1388  * if there is none, seek to the beginning of the segment.
1389  *
1390  * Called with STREAM_LOCK
1391  */
1392 static gboolean
1393 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1394     guint32 seqnum, GstSeekFlags flags)
1395 {
1396   gint64 desired_offset;
1397   guint i;
1398
1399   desired_offset = segment->position;
1400
1401   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1402       GST_TIME_ARGS (desired_offset));
1403
1404   /* may not have enough fragmented info to do this adjustment,
1405    * and we can't scan (and probably should not) at this time with
1406    * possibly flushing upstream */
1407   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1408     gint64 min_offset;
1409     gboolean next, before, after;
1410
1411     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1412     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1413     next = after && !before;
1414     if (segment->rate < 0)
1415       next = !next;
1416
1417     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1418         NULL);
1419     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1420         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1421     desired_offset = min_offset;
1422   }
1423
1424   /* and set all streams to the final position */
1425   GST_OBJECT_LOCK (qtdemux);
1426   gst_flow_combiner_reset (qtdemux->flowcombiner);
1427   GST_OBJECT_UNLOCK (qtdemux);
1428   qtdemux->segment_seqnum = seqnum;
1429   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1430     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1431
1432     stream->time_position = desired_offset;
1433     stream->accumulated_base = 0;
1434     stream->sample_index = -1;
1435     stream->offset_in_sample = 0;
1436     stream->segment_index = -1;
1437     stream->sent_eos = FALSE;
1438     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1439
1440     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1441       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1442   }
1443   segment->position = desired_offset;
1444   if (segment->rate >= 0) {
1445     segment->start = desired_offset;
1446     /* We need to update time as we update start in that direction */
1447     segment->time = desired_offset;
1448
1449     /* we stop at the end */
1450     if (segment->stop == -1)
1451       segment->stop = segment->duration;
1452   } else {
1453     segment->stop = desired_offset;
1454   }
1455
1456   if (qtdemux->fragmented)
1457     qtdemux->fragmented_seek_pending = TRUE;
1458
1459   return TRUE;
1460 }
1461
1462 /* do a seek in pull based mode */
1463 static gboolean
1464 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1465 {
1466   gdouble rate = 1.0;
1467   GstFormat format;
1468   GstSeekFlags flags;
1469   GstSeekType cur_type, stop_type;
1470   gint64 cur, stop;
1471   gboolean flush, instant_rate_change;
1472   gboolean update;
1473   GstSegment seeksegment;
1474   guint32 seqnum = GST_SEQNUM_INVALID;
1475   GstEvent *flush_event;
1476   gboolean ret;
1477
1478   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1479
1480   gst_event_parse_seek (event, &rate, &format, &flags,
1481       &cur_type, &cur, &stop_type, &stop);
1482   seqnum = gst_event_get_seqnum (event);
1483
1484   /* we have to have a format as the segment format. Try to convert
1485    * if not. */
1486   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1487           stop_type, &stop))
1488     goto no_format;
1489
1490   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1491
1492   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1493   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1494
1495   /* Directly send the instant-rate-change event here before taking the
1496    * stream-lock so that it can be applied as soon as possible */
1497   if (instant_rate_change) {
1498     GstEvent *ev;
1499
1500     /* instant rate change only supported if direction does not change. All
1501      * other requirements are already checked before creating the seek event
1502      * but let's double-check here to be sure */
1503     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1504         (qtdemux->segment.rate < 0 && rate > 0) ||
1505         cur_type != GST_SEEK_TYPE_NONE ||
1506         stop_type != GST_SEEK_TYPE_NONE || flush) {
1507       GST_ERROR_OBJECT (qtdemux,
1508           "Instant rate change seeks only supported in the "
1509           "same direction, without flushing and position change");
1510       return FALSE;
1511     }
1512
1513     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1514         (GstSegmentFlags) flags);
1515     gst_event_set_seqnum (ev, seqnum);
1516     gst_qtdemux_push_event (qtdemux, ev);
1517     return TRUE;
1518   }
1519
1520   /* stop streaming, either by flushing or by pausing the task */
1521   if (flush) {
1522     flush_event = gst_event_new_flush_start ();
1523     if (seqnum != GST_SEQNUM_INVALID)
1524       gst_event_set_seqnum (flush_event, seqnum);
1525     /* unlock upstream pull_range */
1526     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1527     /* make sure out loop function exits */
1528     gst_qtdemux_push_event (qtdemux, flush_event);
1529   } else {
1530     /* non flushing seek, pause the task */
1531     gst_pad_pause_task (qtdemux->sinkpad);
1532   }
1533
1534   /* wait for streaming to finish */
1535   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1536
1537   /* copy segment, we need this because we still need the old
1538    * segment when we close the current segment. */
1539   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1540
1541   /* configure the segment with the seek variables */
1542   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1543   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1544           cur_type, cur, stop_type, stop, &update)) {
1545     ret = FALSE;
1546     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1547   } else {
1548     /* now do the seek */
1549     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1550   }
1551
1552   /* prepare for streaming again */
1553   if (flush) {
1554     flush_event = gst_event_new_flush_stop (TRUE);
1555     if (seqnum != GST_SEQNUM_INVALID)
1556       gst_event_set_seqnum (flush_event, seqnum);
1557
1558     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1559     gst_qtdemux_push_event (qtdemux, flush_event);
1560   }
1561
1562   /* commit the new segment */
1563   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1564
1565   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1566     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1567         qtdemux->segment.format, qtdemux->segment.position);
1568     if (seqnum != GST_SEQNUM_INVALID)
1569       gst_message_set_seqnum (msg, seqnum);
1570     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1571   }
1572
1573   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1574   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1575       qtdemux->sinkpad, NULL);
1576
1577   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1578
1579   return ret;
1580
1581   /* ERRORS */
1582 no_format:
1583   {
1584     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1585     return FALSE;
1586   }
1587 }
1588
1589 static gboolean
1590 qtdemux_ensure_index (GstQTDemux * qtdemux)
1591 {
1592   guint i;
1593
1594   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1595
1596   /* Build complete index */
1597   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1598     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1599
1600     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1601       GST_LOG_OBJECT (qtdemux,
1602           "Building complete index of track-id %u for seeking failed!",
1603           stream->track_id);
1604       return FALSE;
1605     }
1606   }
1607
1608   return TRUE;
1609 }
1610
1611 static gboolean
1612 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1613     GstEvent * event)
1614 {
1615   gboolean res = TRUE;
1616   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1617
1618   switch (GST_EVENT_TYPE (event)) {
1619     case GST_EVENT_RECONFIGURE:
1620       GST_OBJECT_LOCK (qtdemux);
1621       gst_flow_combiner_reset (qtdemux->flowcombiner);
1622       GST_OBJECT_UNLOCK (qtdemux);
1623       res = gst_pad_event_default (pad, parent, event);
1624       break;
1625     case GST_EVENT_SEEK:
1626     {
1627       GstSeekFlags flags = 0;
1628       GstFormat seek_format;
1629       gboolean instant_rate_change;
1630
1631 #ifndef GST_DISABLE_GST_DEBUG
1632       GstClockTime ts = gst_util_get_timestamp ();
1633 #endif
1634       guint32 seqnum = gst_event_get_seqnum (event);
1635
1636       qtdemux->received_seek = TRUE;
1637
1638       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1639           NULL);
1640       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1641
1642       if (seqnum == qtdemux->segment_seqnum) {
1643         GST_LOG_OBJECT (pad,
1644             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1645         gst_event_unref (event);
1646         return TRUE;
1647       }
1648
1649       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1650         /* seek should be handled by upstream, we might need to re-download fragments */
1651         GST_DEBUG_OBJECT (qtdemux,
1652             "let upstream handle seek for fragmented playback");
1653         goto upstream;
1654       }
1655
1656       if (seek_format == GST_FORMAT_BYTES) {
1657         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1658         gst_event_unref (event);
1659         return FALSE;
1660       }
1661
1662       gst_event_parse_seek_trickmode_interval (event,
1663           &qtdemux->trickmode_interval);
1664
1665       /* Build complete index for seeking;
1666        * if not a fragmented file at least and we're really doing a seek,
1667        * not just an instant-rate-change */
1668       if (!qtdemux->fragmented && !instant_rate_change) {
1669         if (!qtdemux_ensure_index (qtdemux))
1670           goto index_failed;
1671       }
1672 #ifndef GST_DISABLE_GST_DEBUG
1673       ts = gst_util_get_timestamp () - ts;
1674       GST_INFO_OBJECT (qtdemux,
1675           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1676 #endif
1677       if (qtdemux->pullbased) {
1678         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1679       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1680         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1681         res = TRUE;
1682       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1683           && QTDEMUX_N_STREAMS (qtdemux)
1684           && !qtdemux->fragmented) {
1685         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1686       } else {
1687         GST_DEBUG_OBJECT (qtdemux,
1688             "ignoring seek in push mode in current state");
1689         res = FALSE;
1690       }
1691       gst_event_unref (event);
1692     }
1693       break;
1694     default:
1695     upstream:
1696       res = gst_pad_event_default (pad, parent, event);
1697       break;
1698   }
1699
1700 done:
1701   return res;
1702
1703   /* ERRORS */
1704 index_failed:
1705   {
1706     GST_ERROR_OBJECT (qtdemux, "Index failed");
1707     gst_event_unref (event);
1708     res = FALSE;
1709     goto done;
1710   }
1711 }
1712
1713 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1714  *
1715  * If @fw is false, the coding order is explored backwards.
1716  *
1717  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1718  * sample is found for that track.
1719  *
1720  * The stream and sample index of the sample with the minimum offset in the direction explored
1721  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1722  *
1723  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1724  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1725  * @_stream and @_index. */
1726 static void
1727 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1728     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1729 {
1730   gint i, index;
1731   gint64 time, min_time;
1732   QtDemuxStream *stream;
1733   gint iter;
1734
1735   min_time = -1;
1736   stream = NULL;
1737   index = -1;
1738
1739   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1740     QtDemuxStream *str;
1741     gint inc;
1742     gboolean set_sample;
1743
1744     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1745     set_sample = !set;
1746
1747     if (fw) {
1748       i = 0;
1749       inc = 1;
1750     } else {
1751       i = str->n_samples - 1;
1752       inc = -1;
1753     }
1754
1755     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1756       if (str->samples[i].size == 0)
1757         continue;
1758
1759       if (fw && (str->samples[i].offset < byte_pos))
1760         continue;
1761
1762       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1763         continue;
1764
1765       /* move stream to first available sample */
1766       if (set) {
1767         gst_qtdemux_move_stream (qtdemux, str, i);
1768         set_sample = TRUE;
1769       }
1770
1771       /* avoid index from sparse streams since they might be far away */
1772       if (!CUR_STREAM (str)->sparse) {
1773         /* determine min/max time */
1774         time = QTSAMPLE_PTS (str, &str->samples[i]);
1775         if (min_time == -1 || (!fw && time > min_time) ||
1776             (fw && time < min_time)) {
1777           min_time = time;
1778         }
1779
1780         /* determine stream with leading sample, to get its position */
1781         if (!stream ||
1782             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1783             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1784           stream = str;
1785           index = i;
1786         }
1787       }
1788       break;
1789     }
1790
1791     /* no sample for this stream, mark eos */
1792     if (!set_sample)
1793       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1794   }
1795
1796   if (_time)
1797     *_time = min_time;
1798   if (_stream)
1799     *_stream = stream;
1800   if (_index)
1801     *_index = index;
1802 }
1803
1804 /* Copied from mpegtsbase code */
1805 /* FIXME: replace this function when we add new util function for stream-id creation */
1806 static gchar *
1807 _get_upstream_id (GstQTDemux * demux)
1808 {
1809   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1810
1811   if (!upstream_id) {
1812     /* Try to create one from the upstream URI, else use a randome number */
1813     GstQuery *query;
1814     gchar *uri = NULL;
1815
1816     /* Try to generate one from the URI query and
1817      * if it fails take a random number instead */
1818     query = gst_query_new_uri ();
1819     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1820       gst_query_parse_uri (query, &uri);
1821     }
1822
1823     if (uri) {
1824       GChecksum *cs;
1825
1826       /* And then generate an SHA256 sum of the URI */
1827       cs = g_checksum_new (G_CHECKSUM_SHA256);
1828       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1829       g_free (uri);
1830       upstream_id = g_strdup (g_checksum_get_string (cs));
1831       g_checksum_free (cs);
1832     } else {
1833       /* Just get some random number if the URI query fails */
1834       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1835           "implementing a deterministic way of creating a stream-id");
1836       upstream_id =
1837           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1838           g_random_int (), g_random_int ());
1839     }
1840
1841     gst_query_unref (query);
1842   }
1843   return upstream_id;
1844 }
1845
1846 static QtDemuxStream *
1847 _create_stream (GstQTDemux * demux, guint32 track_id)
1848 {
1849   QtDemuxStream *stream;
1850   gchar *upstream_id;
1851
1852   stream = g_new0 (QtDemuxStream, 1);
1853   stream->demux = demux;
1854   stream->track_id = track_id;
1855   upstream_id = _get_upstream_id (demux);
1856   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1857   g_free (upstream_id);
1858   /* new streams always need a discont */
1859   stream->discont = TRUE;
1860   /* we enable clipping for raw audio/video streams */
1861   stream->need_clip = FALSE;
1862   stream->process_func = NULL;
1863   stream->segment_index = -1;
1864   stream->time_position = 0;
1865   stream->sample_index = -1;
1866   stream->offset_in_sample = 0;
1867   stream->new_stream = TRUE;
1868   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1869   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1870   stream->protected = FALSE;
1871   stream->protection_scheme_type = 0;
1872   stream->protection_scheme_version = 0;
1873   stream->protection_scheme_info = NULL;
1874   stream->n_samples_moof = 0;
1875   stream->duration_moof = 0;
1876   stream->duration_last_moof = 0;
1877   stream->alignment = 1;
1878   stream->stream_tags = gst_tag_list_new_empty ();
1879   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1880   g_queue_init (&stream->protection_scheme_event_queue);
1881   stream->ref_count = 1;
1882   /* consistent default for push based mode */
1883   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1884   return stream;
1885 }
1886
1887 static gboolean
1888 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1889 {
1890   GstStructure *structure;
1891   const gchar *variant;
1892   const GstCaps *mediacaps = NULL;
1893
1894   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1895
1896   structure = gst_caps_get_structure (caps, 0);
1897   variant = gst_structure_get_string (structure, "variant");
1898
1899   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1900     QtDemuxStream *stream;
1901     const GValue *value;
1902
1903     demux->fragmented = TRUE;
1904     demux->mss_mode = TRUE;
1905
1906     if (QTDEMUX_N_STREAMS (demux) > 1) {
1907       /* can't do this, we can only renegotiate for another mss format */
1908       return FALSE;
1909     }
1910
1911     value = gst_structure_get_value (structure, "media-caps");
1912     /* create stream */
1913     if (value) {
1914       const GValue *timescale_v;
1915
1916       /* TODO update when stream changes during playback */
1917
1918       if (QTDEMUX_N_STREAMS (demux) == 0) {
1919         stream = _create_stream (demux, 1);
1920         g_ptr_array_add (demux->active_streams, stream);
1921         /* mss has no stsd/stsd entry, use id 0 as default */
1922         stream->stsd_entries_length = 1;
1923         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1924         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1925       } else {
1926         stream = QTDEMUX_NTH_STREAM (demux, 0);
1927       }
1928
1929       timescale_v = gst_structure_get_value (structure, "timescale");
1930       if (timescale_v) {
1931         stream->timescale = g_value_get_uint64 (timescale_v);
1932       } else {
1933         /* default mss timescale */
1934         stream->timescale = 10000000;
1935       }
1936       demux->timescale = stream->timescale;
1937
1938       mediacaps = gst_value_get_caps (value);
1939       if (!CUR_STREAM (stream)->caps
1940           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1941         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1942             mediacaps);
1943         stream->new_caps = TRUE;
1944       }
1945       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1946       structure = gst_caps_get_structure (mediacaps, 0);
1947       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1948         stream->subtype = FOURCC_vide;
1949
1950         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1951         gst_structure_get_int (structure, "height",
1952             &CUR_STREAM (stream)->height);
1953         gst_structure_get_fraction (structure, "framerate",
1954             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1955       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1956         gint rate = 0;
1957         stream->subtype = FOURCC_soun;
1958         gst_structure_get_int (structure, "channels",
1959             &CUR_STREAM (stream)->n_channels);
1960         gst_structure_get_int (structure, "rate", &rate);
1961         CUR_STREAM (stream)->rate = rate;
1962       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1963         if (gst_structure_has_field (structure, "original-media-type")) {
1964           const gchar *media_type =
1965               gst_structure_get_string (structure, "original-media-type");
1966           if (g_str_has_prefix (media_type, "video")) {
1967             stream->subtype = FOURCC_vide;
1968           } else if (g_str_has_prefix (media_type, "audio")) {
1969             stream->subtype = FOURCC_soun;
1970           }
1971         }
1972       }
1973     }
1974     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1975   } else {
1976     demux->mss_mode = FALSE;
1977   }
1978
1979   return TRUE;
1980 }
1981
1982 static void
1983 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1984 {
1985   gint i;
1986
1987   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1988
1989   if (hard || qtdemux->upstream_format_is_time) {
1990     qtdemux->state = QTDEMUX_STATE_INITIAL;
1991     qtdemux->neededbytes = 16;
1992     qtdemux->todrop = 0;
1993     qtdemux->pullbased = FALSE;
1994     g_clear_pointer (&qtdemux->redirect_location, g_free);
1995     qtdemux->first_mdat = -1;
1996     qtdemux->header_size = 0;
1997     qtdemux->mdatoffset = -1;
1998     qtdemux->restoredata_offset = -1;
1999     if (qtdemux->mdatbuffer)
2000       gst_buffer_unref (qtdemux->mdatbuffer);
2001     if (qtdemux->restoredata_buffer)
2002       gst_buffer_unref (qtdemux->restoredata_buffer);
2003     qtdemux->mdatbuffer = NULL;
2004     qtdemux->restoredata_buffer = NULL;
2005     qtdemux->mdatleft = 0;
2006     qtdemux->mdatsize = 0;
2007     if (qtdemux->comp_brands)
2008       gst_buffer_unref (qtdemux->comp_brands);
2009     qtdemux->comp_brands = NULL;
2010     qtdemux->last_moov_offset = -1;
2011     if (qtdemux->moov_node_compressed) {
2012       g_node_destroy (qtdemux->moov_node_compressed);
2013       if (qtdemux->moov_node)
2014         g_free (qtdemux->moov_node->data);
2015     }
2016     qtdemux->moov_node_compressed = NULL;
2017     if (qtdemux->moov_node)
2018       g_node_destroy (qtdemux->moov_node);
2019     qtdemux->moov_node = NULL;
2020     if (qtdemux->tag_list)
2021       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2022     qtdemux->tag_list = gst_tag_list_new_empty ();
2023     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2024 #if 0
2025     if (qtdemux->element_index)
2026       gst_object_unref (qtdemux->element_index);
2027     qtdemux->element_index = NULL;
2028 #endif
2029     qtdemux->major_brand = 0;
2030     qtdemux->upstream_format_is_time = FALSE;
2031     qtdemux->upstream_seekable = FALSE;
2032     qtdemux->upstream_size = 0;
2033
2034     qtdemux->fragment_start = -1;
2035     qtdemux->fragment_start_offset = -1;
2036     qtdemux->duration = 0;
2037     qtdemux->moof_offset = 0;
2038     qtdemux->chapters_track_id = 0;
2039     qtdemux->have_group_id = FALSE;
2040     qtdemux->group_id = G_MAXUINT;
2041
2042     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2043         NULL);
2044     g_queue_clear (&qtdemux->protection_event_queue);
2045
2046     qtdemux->received_seek = FALSE;
2047     qtdemux->first_moof_already_parsed = FALSE;
2048   }
2049   qtdemux->offset = 0;
2050   gst_adapter_clear (qtdemux->adapter);
2051   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2052   qtdemux->need_segment = TRUE;
2053
2054   if (hard) {
2055     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2056     qtdemux->trickmode_interval = 0;
2057     g_ptr_array_set_size (qtdemux->active_streams, 0);
2058     g_ptr_array_set_size (qtdemux->old_streams, 0);
2059     qtdemux->n_video_streams = 0;
2060     qtdemux->n_audio_streams = 0;
2061     qtdemux->n_sub_streams = 0;
2062     qtdemux->n_meta_streams = 0;
2063     qtdemux->exposed = FALSE;
2064     qtdemux->fragmented = FALSE;
2065     qtdemux->mss_mode = FALSE;
2066     gst_caps_replace (&qtdemux->media_caps, NULL);
2067     qtdemux->timescale = 0;
2068     qtdemux->got_moov = FALSE;
2069     qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
2070     qtdemux->cenc_aux_info_offset = 0;
2071     g_free (qtdemux->cenc_aux_info_sizes);
2072     qtdemux->cenc_aux_info_sizes = NULL;
2073     qtdemux->cenc_aux_sample_count = 0;
2074     if (qtdemux->protection_system_ids) {
2075       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2076       qtdemux->protection_system_ids = NULL;
2077     }
2078     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2079         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2080         GST_BIN_FLAG_STREAMS_AWARE);
2081
2082     if (qtdemux->preferred_protection_system_id) {
2083       g_free (qtdemux->preferred_protection_system_id);
2084       qtdemux->preferred_protection_system_id = NULL;
2085     }
2086   } else if (qtdemux->mss_mode) {
2087     gst_flow_combiner_reset (qtdemux->flowcombiner);
2088     g_ptr_array_foreach (qtdemux->active_streams,
2089         (GFunc) gst_qtdemux_stream_clear, NULL);
2090   } else {
2091     gst_flow_combiner_reset (qtdemux->flowcombiner);
2092     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2093       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2094       stream->sent_eos = FALSE;
2095       stream->time_position = 0;
2096       stream->accumulated_base = 0;
2097       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2098     }
2099   }
2100 }
2101
2102
2103 /* Maps the @segment to the qt edts internal segments and pushes
2104  * the corresponding segment event.
2105  *
2106  * If it ends up being at a empty segment, a gap will be pushed and the next
2107  * edts segment will be activated in sequence.
2108  *
2109  * To be used in push-mode only */
2110 static void
2111 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2112 {
2113   gint i, iter;
2114
2115   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2116     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2117
2118     stream->time_position = segment->start;
2119
2120     /* in push mode we should be guaranteed that we will have empty segments
2121      * at the beginning and then one segment after, other scenarios are not
2122      * supported and are discarded when parsing the edts */
2123     for (i = 0; i < stream->n_segments; i++) {
2124       if (stream->segments[i].stop_time > segment->start) {
2125         /* push the empty segment and move to the next one */
2126         gst_qtdemux_activate_segment (qtdemux, stream, i,
2127             stream->time_position);
2128         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2129           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2130               stream->time_position);
2131
2132           /* accumulate previous segments */
2133           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2134             stream->accumulated_base +=
2135                 (stream->segment.stop -
2136                 stream->segment.start) / ABS (stream->segment.rate);
2137           continue;
2138         }
2139
2140         g_assert (i == stream->n_segments - 1);
2141       }
2142     }
2143   }
2144 }
2145
2146 static void
2147 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2148     GPtrArray * src)
2149 {
2150   guint i;
2151   guint len;
2152
2153   len = src->len;
2154
2155   if (len == 0)
2156     return;
2157
2158   for (i = 0; i < len; i++) {
2159     QtDemuxStream *stream = g_ptr_array_index (src, i);
2160
2161 #ifndef GST_DISABLE_GST_DEBUG
2162     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2163         stream, GST_STR_NULL (stream->stream_id), dest);
2164 #endif
2165     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2166   }
2167
2168   g_ptr_array_set_size (src, 0);
2169 }
2170
2171 static gboolean
2172 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2173     GstEvent * event)
2174 {
2175   GstQTDemux *demux = GST_QTDEMUX (parent);
2176   gboolean res = TRUE;
2177
2178   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2179
2180   switch (GST_EVENT_TYPE (event)) {
2181     case GST_EVENT_SEGMENT:
2182     {
2183       gint64 offset = 0;
2184       QtDemuxStream *stream;
2185       gint idx;
2186       GstSegment segment;
2187
2188       /* some debug output */
2189       gst_event_copy_segment (event, &segment);
2190       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2191           &segment);
2192
2193       if (segment.format == GST_FORMAT_TIME) {
2194         demux->upstream_format_is_time = TRUE;
2195         demux->segment_seqnum = gst_event_get_seqnum (event);
2196       } else {
2197         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2198             "not in time format");
2199
2200         /* chain will send initial newsegment after pads have been added */
2201         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2202           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2203           goto exit;
2204         }
2205       }
2206
2207       /* check if this matches a time seek we received previously
2208        * FIXME for backwards compatibility reasons we use the
2209        * seek_offset here to compare. In the future we might want to
2210        * change this to use the seqnum as it uniquely should identify
2211        * the segment that corresponds to the seek. */
2212       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2213           ", received segment offset %" G_GINT64_FORMAT,
2214           demux->seek_offset, segment.start);
2215       if (segment.format == GST_FORMAT_BYTES
2216           && demux->seek_offset == segment.start) {
2217         GST_OBJECT_LOCK (demux);
2218         offset = segment.start;
2219
2220         segment.format = GST_FORMAT_TIME;
2221         segment.start = demux->push_seek_start;
2222         segment.stop = demux->push_seek_stop;
2223         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2224             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2225             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2226         GST_OBJECT_UNLOCK (demux);
2227       }
2228
2229       /* we only expect a BYTE segment, e.g. following a seek */
2230       if (segment.format == GST_FORMAT_BYTES) {
2231         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2232           offset = segment.start;
2233
2234           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2235               NULL, (gint64 *) & segment.start);
2236           if ((gint64) segment.start < 0)
2237             segment.start = 0;
2238         }
2239         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2240           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2241               NULL, (gint64 *) & segment.stop);
2242           /* keyframe seeking should already arrange for start >= stop,
2243            * but make sure in other rare cases */
2244           segment.stop = MAX (segment.stop, segment.start);
2245         }
2246       } else if (segment.format == GST_FORMAT_TIME) {
2247         /* push all data on the adapter before starting this
2248          * new segment */
2249         gst_qtdemux_process_adapter (demux, TRUE);
2250       } else {
2251         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2252         goto exit;
2253       }
2254
2255       /* We shouldn't modify upstream driven TIME FORMAT segment */
2256       if (!demux->upstream_format_is_time) {
2257         /* accept upstream's notion of segment and distribute along */
2258         segment.format = GST_FORMAT_TIME;
2259         segment.position = segment.time = segment.start;
2260         segment.duration = demux->segment.duration;
2261         segment.base = gst_segment_to_running_time (&demux->segment,
2262             GST_FORMAT_TIME, demux->segment.position);
2263       }
2264
2265       gst_segment_copy_into (&segment, &demux->segment);
2266       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2267
2268       /* map segment to internal qt segments and push on each stream */
2269       if (QTDEMUX_N_STREAMS (demux)) {
2270         demux->need_segment = TRUE;
2271         gst_qtdemux_check_send_pending_segment (demux);
2272       }
2273
2274       /* clear leftover in current segment, if any */
2275       gst_adapter_clear (demux->adapter);
2276
2277       /* set up streaming thread */
2278       demux->offset = offset;
2279       if (demux->upstream_format_is_time) {
2280         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2281             "set values to restart reading from a new atom");
2282         demux->neededbytes = 16;
2283         demux->todrop = 0;
2284       } else {
2285         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2286             NULL);
2287         if (stream) {
2288           demux->todrop = stream->samples[idx].offset - offset;
2289           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2290         } else {
2291           /* set up for EOS */
2292           demux->neededbytes = -1;
2293           demux->todrop = 0;
2294         }
2295       }
2296     exit:
2297       gst_event_unref (event);
2298       res = TRUE;
2299       goto drop;
2300     }
2301     case GST_EVENT_FLUSH_START:
2302     {
2303       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2304         gst_event_unref (event);
2305         goto drop;
2306       }
2307       QTDEMUX_EXPOSE_LOCK (demux);
2308       res = gst_pad_event_default (demux->sinkpad, parent, event);
2309       QTDEMUX_EXPOSE_UNLOCK (demux);
2310       goto drop;
2311     }
2312     case GST_EVENT_FLUSH_STOP:
2313     {
2314       guint64 dur;
2315
2316       dur = demux->segment.duration;
2317       gst_qtdemux_reset (demux, FALSE);
2318       demux->segment.duration = dur;
2319
2320       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2321         gst_event_unref (event);
2322         goto drop;
2323       }
2324       break;
2325     }
2326     case GST_EVENT_EOS:
2327       /* If we are in push mode, and get an EOS before we've seen any streams,
2328        * then error out - we have nowhere to send the EOS */
2329       if (!demux->pullbased) {
2330         gint i;
2331         gboolean has_valid_stream = FALSE;
2332         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2333           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2334             has_valid_stream = TRUE;
2335             break;
2336           }
2337         }
2338         if (!has_valid_stream)
2339           gst_qtdemux_post_no_playable_stream_error (demux);
2340         else {
2341           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2342               (guint) gst_adapter_available (demux->adapter));
2343           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2344             res = FALSE;
2345           }
2346         }
2347       }
2348       break;
2349     case GST_EVENT_CAPS:{
2350       GstCaps *caps = NULL;
2351
2352       gst_event_parse_caps (event, &caps);
2353       gst_qtdemux_setcaps (demux, caps);
2354       res = TRUE;
2355       gst_event_unref (event);
2356       goto drop;
2357     }
2358     case GST_EVENT_PROTECTION:
2359     {
2360       const gchar *system_id = NULL;
2361
2362       gst_event_parse_protection (event, &system_id, NULL, NULL);
2363       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2364           system_id);
2365       gst_qtdemux_append_protection_system_id (demux, system_id);
2366       /* save the event for later, for source pads that have not been created */
2367       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2368       /* send it to all pads that already exist */
2369       gst_qtdemux_push_event (demux, event);
2370       res = TRUE;
2371       goto drop;
2372     }
2373     case GST_EVENT_STREAM_START:
2374     {
2375       res = TRUE;
2376       gst_event_unref (event);
2377
2378       /* Drain all the buffers */
2379       gst_qtdemux_process_adapter (demux, TRUE);
2380       gst_qtdemux_reset (demux, FALSE);
2381       /* We expect new moov box after new stream-start event */
2382       if (demux->exposed) {
2383         gst_qtdemux_stream_concat (demux,
2384             demux->old_streams, demux->active_streams);
2385       }
2386
2387       goto drop;
2388     }
2389     default:
2390       break;
2391   }
2392
2393   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2394
2395 drop:
2396   return res;
2397 }
2398
2399 static gboolean
2400 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2401     GstQuery * query)
2402 {
2403   GstQTDemux *demux = GST_QTDEMUX (parent);
2404   gboolean res = FALSE;
2405
2406   switch (GST_QUERY_TYPE (query)) {
2407     case GST_QUERY_BITRATE:
2408     {
2409       GstClockTime duration;
2410
2411       /* populate demux->upstream_size if not done yet */
2412       gst_qtdemux_check_seekability (demux);
2413
2414       if (demux->upstream_size != -1
2415           && gst_qtdemux_get_duration (demux, &duration)) {
2416         guint bitrate =
2417             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2418             duration);
2419
2420         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2421             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2422             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2423
2424         /* TODO: better results based on ranges/index tables */
2425         gst_query_set_bitrate (query, bitrate);
2426         res = TRUE;
2427       }
2428       break;
2429     }
2430     default:
2431       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2432       break;
2433   }
2434
2435   return res;
2436 }
2437
2438
2439 #if 0
2440 static void
2441 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2442 {
2443   GstQTDemux *demux = GST_QTDEMUX (element);
2444
2445   GST_OBJECT_LOCK (demux);
2446   if (demux->element_index)
2447     gst_object_unref (demux->element_index);
2448   if (index) {
2449     demux->element_index = gst_object_ref (index);
2450   } else {
2451     demux->element_index = NULL;
2452   }
2453   GST_OBJECT_UNLOCK (demux);
2454   /* object lock might be taken again */
2455   if (index)
2456     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2457   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2458       demux->element_index, demux->index_id);
2459 }
2460
2461 static GstIndex *
2462 gst_qtdemux_get_index (GstElement * element)
2463 {
2464   GstIndex *result = NULL;
2465   GstQTDemux *demux = GST_QTDEMUX (element);
2466
2467   GST_OBJECT_LOCK (demux);
2468   if (demux->element_index)
2469     result = gst_object_ref (demux->element_index);
2470   GST_OBJECT_UNLOCK (demux);
2471
2472   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2473
2474   return result;
2475 }
2476 #endif
2477
2478 static void
2479 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2480 {
2481   g_free ((gpointer) stream->stco.data);
2482   stream->stco.data = NULL;
2483   g_free ((gpointer) stream->stsz.data);
2484   stream->stsz.data = NULL;
2485   g_free ((gpointer) stream->stsc.data);
2486   stream->stsc.data = NULL;
2487   g_free ((gpointer) stream->stts.data);
2488   stream->stts.data = NULL;
2489   g_free ((gpointer) stream->stss.data);
2490   stream->stss.data = NULL;
2491   g_free ((gpointer) stream->stps.data);
2492   stream->stps.data = NULL;
2493   g_free ((gpointer) stream->ctts.data);
2494   stream->ctts.data = NULL;
2495 }
2496
2497 static void
2498 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2499 {
2500   g_free (stream->segments);
2501   stream->segments = NULL;
2502   stream->segment_index = -1;
2503   stream->accumulated_base = 0;
2504 }
2505
2506 static void
2507 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2508 {
2509   g_free (stream->samples);
2510   stream->samples = NULL;
2511   gst_qtdemux_stbl_free (stream);
2512
2513   /* fragments */
2514   g_free (stream->ra_entries);
2515   stream->ra_entries = NULL;
2516   stream->n_ra_entries = 0;
2517
2518   stream->sample_index = -1;
2519   stream->stbl_index = -1;
2520   stream->n_samples = 0;
2521   stream->time_position = 0;
2522
2523   stream->n_samples_moof = 0;
2524   stream->duration_moof = 0;
2525   stream->duration_last_moof = 0;
2526 }
2527
2528 static void
2529 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2530 {
2531   gint i;
2532   if (stream->allocator)
2533     gst_object_unref (stream->allocator);
2534   while (stream->buffers) {
2535     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2536     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2537   }
2538   for (i = 0; i < stream->stsd_entries_length; i++) {
2539     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2540     if (entry->rgb8_palette) {
2541       gst_memory_unref (entry->rgb8_palette);
2542       entry->rgb8_palette = NULL;
2543     }
2544     entry->sparse = FALSE;
2545   }
2546
2547   if (stream->stream_tags)
2548     gst_tag_list_unref (stream->stream_tags);
2549
2550   stream->stream_tags = gst_tag_list_new_empty ();
2551   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2552   g_free (stream->redirect_uri);
2553   stream->redirect_uri = NULL;
2554   stream->sent_eos = FALSE;
2555   stream->protected = FALSE;
2556   if (stream->protection_scheme_info) {
2557     if (stream->protection_scheme_type == FOURCC_cenc
2558         || stream->protection_scheme_type == FOURCC_cbcs) {
2559       QtDemuxCencSampleSetInfo *info =
2560           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2561       if (info->default_properties)
2562         gst_structure_free (info->default_properties);
2563       if (info->crypto_info)
2564         g_ptr_array_free (info->crypto_info, TRUE);
2565     }
2566     if (stream->protection_scheme_type == FOURCC_aavd) {
2567       QtDemuxAavdEncryptionInfo *info =
2568           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2569       if (info->default_properties)
2570         gst_structure_free (info->default_properties);
2571     }
2572     g_free (stream->protection_scheme_info);
2573     stream->protection_scheme_info = NULL;
2574   }
2575   stream->protection_scheme_type = 0;
2576   stream->protection_scheme_version = 0;
2577   g_queue_foreach (&stream->protection_scheme_event_queue,
2578       (GFunc) gst_event_unref, NULL);
2579   g_queue_clear (&stream->protection_scheme_event_queue);
2580   gst_qtdemux_stream_flush_segments_data (stream);
2581   gst_qtdemux_stream_flush_samples_data (stream);
2582 }
2583
2584 static void
2585 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2586 {
2587   gint i;
2588   gst_qtdemux_stream_clear (stream);
2589   for (i = 0; i < stream->stsd_entries_length; i++) {
2590     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2591     if (entry->caps) {
2592       gst_caps_unref (entry->caps);
2593       entry->caps = NULL;
2594     }
2595   }
2596   g_free (stream->stsd_entries);
2597   stream->stsd_entries = NULL;
2598   stream->stsd_entries_length = 0;
2599 }
2600
2601 static QtDemuxStream *
2602 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2603 {
2604   g_atomic_int_add (&stream->ref_count, 1);
2605
2606   return stream;
2607 }
2608
2609 static void
2610 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2611 {
2612   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2613     gst_qtdemux_stream_reset (stream);
2614     gst_tag_list_unref (stream->stream_tags);
2615     if (stream->pad) {
2616       GstQTDemux *demux = stream->demux;
2617       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2618       GST_OBJECT_LOCK (demux);
2619       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2620       GST_OBJECT_UNLOCK (demux);
2621     }
2622     g_free (stream->stream_id);
2623     g_free (stream);
2624   }
2625 }
2626
2627 static GstStateChangeReturn
2628 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2629 {
2630   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2631   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2632
2633   switch (transition) {
2634     case GST_STATE_CHANGE_READY_TO_PAUSED:
2635       gst_qtdemux_reset (qtdemux, TRUE);
2636       break;
2637     default:
2638       break;
2639   }
2640
2641   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2642
2643   switch (transition) {
2644     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2645       gst_qtdemux_reset (qtdemux, TRUE);
2646       break;
2647     }
2648     default:
2649       break;
2650   }
2651
2652   return result;
2653 }
2654
2655 static void
2656 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2657 {
2658   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2659
2660   g_return_if_fail (GST_IS_CONTEXT (context));
2661
2662   if (gst_context_has_context_type (context,
2663           "drm-preferred-decryption-system-id")) {
2664     const GstStructure *s;
2665
2666     s = gst_context_get_structure (context);
2667     g_free (qtdemux->preferred_protection_system_id);
2668     qtdemux->preferred_protection_system_id =
2669         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2670     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2671         qtdemux->preferred_protection_system_id);
2672   }
2673
2674   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2675 }
2676
2677 static void
2678 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2679 {
2680   /* counts as header data */
2681   qtdemux->header_size += length;
2682
2683   /* only consider at least a sufficiently complete ftyp atom */
2684   if (length >= 20) {
2685     GstBuffer *buf;
2686     guint32 minor_version;
2687     const guint8 *p;
2688
2689     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2690     GST_DEBUG_OBJECT (qtdemux, "ftyp major brand: %" GST_FOURCC_FORMAT,
2691         GST_FOURCC_ARGS (qtdemux->major_brand));
2692     minor_version = QT_UINT32 (buffer + 12);
2693     GST_DEBUG_OBJECT (qtdemux, "ftyp minor version: %u", minor_version);
2694     if (qtdemux->comp_brands)
2695       gst_buffer_unref (qtdemux->comp_brands);
2696     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2697     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2698
2699     p = buffer + 16;
2700     length = length - 16;
2701     while (length > 0) {
2702       GST_DEBUG_OBJECT (qtdemux, "ftyp compatible brand: %" GST_FOURCC_FORMAT,
2703           GST_FOURCC_ARGS (QT_FOURCC (p)));
2704       length -= 4;
2705       p += 4;
2706     }
2707   }
2708 }
2709
2710 static void
2711 qtdemux_parse_styp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2712 {
2713   /* only consider at least a sufficiently complete styp atom */
2714   if (length >= 20) {
2715     GstBuffer *buf;
2716     guint32 major_brand;
2717     guint32 minor_version;
2718     const guint8 *p;
2719
2720     major_brand = QT_FOURCC (buffer + 8);
2721     GST_DEBUG_OBJECT (qtdemux, "styp major brand: %" GST_FOURCC_FORMAT,
2722         GST_FOURCC_ARGS (major_brand));
2723     minor_version = QT_UINT32 (buffer + 12);
2724     GST_DEBUG_OBJECT (qtdemux, "styp minor version: %u", minor_version);
2725     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2726     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2727
2728     p = buffer + 16;
2729     length = length - 16;
2730     while (length > 0) {
2731       GST_DEBUG_OBJECT (qtdemux, "styp compatible brand: %" GST_FOURCC_FORMAT,
2732           GST_FOURCC_ARGS (QT_FOURCC (p)));
2733       length -= 4;
2734       p += 4;
2735     }
2736   }
2737 }
2738
2739 static void
2740 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2741     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2742     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2743     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2744     const guint8 * constant_iv)
2745 {
2746   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2747   gst_buffer_fill (kid_buf, 0, kid, 16);
2748   if (info->default_properties)
2749     gst_structure_free (info->default_properties);
2750   info->default_properties =
2751       gst_structure_new ("application/x-cenc",
2752       "iv_size", G_TYPE_UINT, iv_size,
2753       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2754       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2755   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2756       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2757   gst_buffer_unref (kid_buf);
2758   if (protection_scheme_type == FOURCC_cbcs) {
2759     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2760       gst_structure_set (info->default_properties, "crypt_byte_block",
2761           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2762           skip_byte_block, NULL);
2763     }
2764     if (constant_iv != NULL) {
2765       GstBuffer *constant_iv_buf =
2766           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2767       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2768       gst_structure_set (info->default_properties, "constant_iv_size",
2769           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2770           NULL);
2771       gst_buffer_unref (constant_iv_buf);
2772     }
2773     gst_structure_set (info->default_properties, "cipher-mode",
2774         G_TYPE_STRING, "cbcs", NULL);
2775   } else {
2776     gst_structure_set (info->default_properties, "cipher-mode",
2777         G_TYPE_STRING, "cenc", NULL);
2778   }
2779 }
2780
2781 static gboolean
2782 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2783     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2784 {
2785   guint32 algorithm_id = 0;
2786   const guint8 *kid;
2787   gboolean is_encrypted = TRUE;
2788   guint8 iv_size = 8;
2789
2790   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2791     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2792     return FALSE;
2793   }
2794
2795   algorithm_id >>= 8;
2796   if (algorithm_id == 0) {
2797     is_encrypted = FALSE;
2798   } else if (algorithm_id == 1) {
2799     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2800   } else if (algorithm_id == 2) {
2801     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2802   }
2803
2804   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2805     return FALSE;
2806
2807   if (!gst_byte_reader_get_data (br, 16, &kid))
2808     return FALSE;
2809
2810   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2811       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2812   gst_structure_set (info->default_properties, "piff_algorithm_id",
2813       G_TYPE_UINT, algorithm_id, NULL);
2814   return TRUE;
2815 }
2816
2817
2818 static void
2819 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2820     guint offset)
2821 {
2822   GstByteReader br;
2823   guint8 version;
2824   guint32 flags = 0;
2825   guint i;
2826   guint iv_size = 8;
2827   QtDemuxStream *stream;
2828   GstStructure *structure;
2829   QtDemuxCencSampleSetInfo *ss_info = NULL;
2830   const gchar *system_id;
2831   gboolean uses_sub_sample_encryption = FALSE;
2832   guint32 sample_count;
2833
2834   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2835     return;
2836
2837   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2838
2839   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2840   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2841     GST_WARNING_OBJECT (qtdemux,
2842         "Attempting PIFF box parsing on an unencrypted stream.");
2843     return;
2844   }
2845
2846   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2847       G_TYPE_STRING, &system_id, NULL);
2848   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2849
2850   stream->protected = TRUE;
2851   stream->protection_scheme_type = FOURCC_cenc;
2852
2853   if (!stream->protection_scheme_info)
2854     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2855
2856   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2857   if (!ss_info->default_properties) {
2858     ss_info->default_properties =
2859         gst_structure_new ("application/x-cenc",
2860         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2861         NULL);
2862
2863   }
2864
2865   if (ss_info->crypto_info) {
2866     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2867     g_ptr_array_free (ss_info->crypto_info, TRUE);
2868     ss_info->crypto_info = NULL;
2869   }
2870
2871   /* skip UUID */
2872   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2873
2874   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2875     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2876     return;
2877   }
2878
2879   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2880     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2881     return;
2882   }
2883
2884   if ((flags & 0x000001)) {
2885     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2886             &br))
2887       return;
2888   } else if ((flags & 0x000002)) {
2889     uses_sub_sample_encryption = TRUE;
2890   }
2891
2892   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2893           &iv_size)) {
2894     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2895     return;
2896   }
2897
2898   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2899     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2900     return;
2901   }
2902
2903   ss_info->crypto_info =
2904       g_ptr_array_new_full (sample_count,
2905       (GDestroyNotify) qtdemux_gst_structure_free);
2906
2907   for (i = 0; i < sample_count; ++i) {
2908     GstStructure *properties;
2909     guint8 *data;
2910     GstBuffer *buf;
2911
2912     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2913     if (properties == NULL) {
2914       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2915       qtdemux->cenc_aux_sample_count = i;
2916       return;
2917     }
2918
2919     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2920       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2921       gst_structure_free (properties);
2922       qtdemux->cenc_aux_sample_count = i;
2923       return;
2924     }
2925     buf = gst_buffer_new_wrapped (data, iv_size);
2926     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2927     gst_buffer_unref (buf);
2928
2929     if (uses_sub_sample_encryption) {
2930       guint16 n_subsamples;
2931       const GValue *kid_buf_value;
2932
2933       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2934           || n_subsamples == 0) {
2935         GST_ERROR_OBJECT (qtdemux,
2936             "failed to get subsample count for sample %u", i);
2937         gst_structure_free (properties);
2938         qtdemux->cenc_aux_sample_count = i;
2939         return;
2940       }
2941       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2942       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2943         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2944             i);
2945         gst_structure_free (properties);
2946         qtdemux->cenc_aux_sample_count = i;
2947         return;
2948       }
2949       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2950
2951       kid_buf_value =
2952           gst_structure_get_value (ss_info->default_properties, "kid");
2953
2954       gst_structure_set (properties,
2955           "subsample_count", G_TYPE_UINT, n_subsamples,
2956           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2957       gst_structure_set_value (properties, "kid", kid_buf_value);
2958       gst_buffer_unref (buf);
2959     } else {
2960       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2961     }
2962
2963     g_ptr_array_add (ss_info->crypto_info, properties);
2964   }
2965
2966   qtdemux->cenc_aux_sample_count = sample_count;
2967 }
2968
2969 static void
2970 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2971 {
2972   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2973     0x97, 0xA9, 0x42, 0xE8,
2974     0x9C, 0x71, 0x99, 0x94,
2975     0x91, 0xE3, 0xAF, 0xAC
2976   };
2977   static const guint8 playready_uuid[] = {
2978     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2979     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2980   };
2981
2982   static const guint8 piff_sample_encryption_uuid[] = {
2983     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2984     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2985   };
2986
2987   guint offset;
2988
2989   /* counts as header data */
2990   qtdemux->header_size += length;
2991
2992   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2993
2994   if (length <= offset + 16) {
2995     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2996     return;
2997   }
2998
2999   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3000     GstBuffer *buf;
3001     GstTagList *taglist;
3002
3003     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3004         length - offset - 16, NULL);
3005     taglist = gst_tag_list_from_xmp_buffer (buf);
3006     gst_buffer_unref (buf);
3007
3008     /* make sure we have a usable taglist */
3009     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3010
3011     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3012
3013   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3014     int len;
3015     const gunichar2 *s_utf16;
3016     char *contents;
3017
3018     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3019     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3020     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3021     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3022
3023     g_free (contents);
3024
3025     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3026         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3027         (NULL));
3028   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3029     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3030   } else {
3031     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3032         GST_READ_UINT32_LE (buffer + offset),
3033         GST_READ_UINT32_LE (buffer + offset + 4),
3034         GST_READ_UINT32_LE (buffer + offset + 8),
3035         GST_READ_UINT32_LE (buffer + offset + 12));
3036   }
3037 }
3038
3039 static void
3040 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3041 {
3042   GstSidxParser sidx_parser;
3043   GstIsoffParserResult res;
3044   guint consumed;
3045
3046   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3047
3048   res =
3049       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3050       &consumed);
3051   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3052   if (res == GST_ISOFF_QT_PARSER_DONE) {
3053     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3054   }
3055   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3056 }
3057
3058 static void
3059 qtdemux_parse_cstb (GstQTDemux * qtdemux, GstByteReader * data)
3060 {
3061   guint64 start_time;
3062   guint32 entry_count;
3063
3064   GST_DEBUG_OBJECT (qtdemux, "Parsing CorrectStartTime box");
3065
3066   qtdemux->start_utc_time = GST_CLOCK_TIME_NONE;
3067
3068   if (gst_byte_reader_get_remaining (data) < 4) {
3069     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3070     return;
3071   }
3072
3073   entry_count = gst_byte_reader_get_uint32_be_unchecked (data);
3074   if (entry_count == 0)
3075     return;
3076
3077   /* XXX: We assume that all start times are the same as different start times
3078    * would violate the MP4 synchronization model, so we just take the first
3079    * one here and apply it to all tracks.
3080    */
3081
3082   if (gst_byte_reader_get_remaining (data) < entry_count * 12) {
3083     GST_WARNING_OBJECT (qtdemux, "Too small CorrectStartTime box");
3084     return;
3085   }
3086
3087   /* Skip track id */
3088   gst_byte_reader_skip_unchecked (data, 4);
3089
3090   /* In 100ns intervals */
3091   start_time = gst_byte_reader_get_uint64_be_unchecked (data);
3092
3093   /* Convert from Jan 1 1601 to Jan 1 1970 */
3094   if (start_time < 11644473600 * G_GUINT64_CONSTANT (10000000)) {
3095     GST_WARNING_OBJECT (qtdemux, "Start UTC time before UNIX epoch");
3096     return;
3097   }
3098   start_time -= 11644473600 * G_GUINT64_CONSTANT (10000000);
3099
3100   /* Convert to GstClockTime */
3101   start_time *= 100;
3102
3103   GST_DEBUG_OBJECT (qtdemux, "Start UTC time: %" GST_TIME_FORMAT,
3104       GST_TIME_ARGS (start_time));
3105
3106   qtdemux->start_utc_time = start_time;
3107 }
3108
3109 /* caller verifies at least 8 bytes in buf */
3110 static void
3111 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3112     guint64 * plength, guint32 * pfourcc)
3113 {
3114   guint64 length;
3115   guint32 fourcc;
3116
3117   length = QT_UINT32 (data);
3118   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3119   fourcc = QT_FOURCC (data + 4);
3120   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3121
3122   if (length == 0) {
3123     length = G_MAXUINT64;
3124   } else if (length == 1 && size >= 16) {
3125     /* this means we have an extended size, which is the 64 bit value of
3126      * the next 8 bytes */
3127     length = QT_UINT64 (data + 8);
3128     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3129   }
3130
3131   if (plength)
3132     *plength = length;
3133   if (pfourcc)
3134     *pfourcc = fourcc;
3135 }
3136
3137 static gboolean
3138 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3139 {
3140   guint32 version = 0;
3141   GstClockTime duration = 0;
3142
3143   if (!gst_byte_reader_get_uint32_be (br, &version))
3144     goto failed;
3145
3146   version >>= 24;
3147   if (version == 1) {
3148     if (!gst_byte_reader_get_uint64_be (br, &duration))
3149       goto failed;
3150   } else {
3151     guint32 dur = 0;
3152
3153     if (!gst_byte_reader_get_uint32_be (br, &dur))
3154       goto failed;
3155     duration = dur;
3156   }
3157
3158   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3159   qtdemux->duration = duration;
3160
3161   return TRUE;
3162
3163 failed:
3164   {
3165     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3166     return FALSE;
3167   }
3168 }
3169
3170 static gboolean
3171 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3172     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3173 {
3174   if (!stream->parsed_trex && qtdemux->moov_node) {
3175     GNode *mvex, *trex;
3176     GstByteReader trex_data;
3177
3178     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3179     if (mvex) {
3180       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3181           &trex_data);
3182       while (trex) {
3183         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3184
3185         /* skip version/flags */
3186         if (!gst_byte_reader_skip (&trex_data, 4))
3187           goto next;
3188         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3189           goto next;
3190         if (id != stream->track_id)
3191           goto next;
3192         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3193           goto next;
3194         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3195           goto next;
3196         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3197           goto next;
3198         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3199           goto next;
3200
3201         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3202             "duration %d,  size %d, flags 0x%x", stream->track_id,
3203             dur, size, flags);
3204
3205         stream->parsed_trex = TRUE;
3206         stream->def_sample_description_index = sdi;
3207         stream->def_sample_duration = dur;
3208         stream->def_sample_size = size;
3209         stream->def_sample_flags = flags;
3210
3211       next:
3212         /* iterate all siblings */
3213         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3214             &trex_data);
3215       }
3216     }
3217   }
3218
3219   *ds_duration = stream->def_sample_duration;
3220   *ds_size = stream->def_sample_size;
3221   *ds_flags = stream->def_sample_flags;
3222
3223   /* even then, above values are better than random ... */
3224   if (G_UNLIKELY (!stream->parsed_trex)) {
3225     GST_WARNING_OBJECT (qtdemux,
3226         "failed to find fragment defaults for stream %d", stream->track_id);
3227     return FALSE;
3228   }
3229
3230   return TRUE;
3231 }
3232
3233 /* This method should be called whenever a more accurate duration might
3234  * have been found. It will update all relevant variables if/where needed
3235  */
3236 static void
3237 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3238 {
3239   guint i;
3240   guint64 movdur;
3241   GstClockTime prevdur;
3242
3243   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3244
3245   if (movdur > qtdemux->duration) {
3246     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3247     GST_DEBUG_OBJECT (qtdemux,
3248         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3249         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3250     qtdemux->duration = movdur;
3251     GST_DEBUG_OBJECT (qtdemux,
3252         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3253         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3254         GST_TIME_ARGS (qtdemux->segment.stop));
3255     if (qtdemux->segment.duration == prevdur) {
3256       /* If the current segment has duration/stop identical to previous duration
3257        * update them also (because they were set at that point in time with
3258        * the wrong duration */
3259       /* We convert the value *from* the timescale version to avoid rounding errors */
3260       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3261       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3262       qtdemux->segment.duration = fixeddur;
3263       qtdemux->segment.stop = fixeddur;
3264     }
3265   }
3266
3267   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3268     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3269
3270     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3271     if (movdur > stream->duration) {
3272       GST_DEBUG_OBJECT (qtdemux,
3273           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3274           GST_TIME_ARGS (duration));
3275       stream->duration = movdur;
3276       /* internal duration tracking state has been updated above, so */
3277       /* preserve an open-ended dummy segment rather than repeatedly updating
3278        * it and spamming downstream accordingly with segment events */
3279       /* also mangle the edit list end time when fragmented with a single edit
3280        * list that may only cover any non-fragmented data */
3281       if ((stream->dummy_segment ||
3282               (qtdemux->fragmented && stream->n_segments == 1)) &&
3283           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3284         /* Update all dummy values to new duration */
3285         stream->segments[0].stop_time = duration;
3286         stream->segments[0].duration = duration;
3287         stream->segments[0].media_stop = duration;
3288
3289         /* let downstream know we possibly have a new stop time */
3290         if (stream->segment_index != -1) {
3291           GstClockTime pos;
3292
3293           if (qtdemux->segment.rate >= 0) {
3294             pos = stream->segment.start;
3295           } else {
3296             pos = stream->segment.stop;
3297           }
3298
3299           gst_qtdemux_stream_update_segment (qtdemux, stream,
3300               stream->segment_index, pos, NULL, NULL);
3301         }
3302       }
3303     }
3304   }
3305 }
3306
3307 static gboolean
3308 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3309     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3310     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3311     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3312     gboolean has_tfdt)
3313 {
3314   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3315   guint64 timestamp;
3316   gint32 data_offset = 0;
3317   guint8 version;
3318   guint32 flags = 0, first_flags = 0, samples_count = 0;
3319   gint i;
3320   guint8 *data;
3321   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3322   QtDemuxSample *sample;
3323   gboolean ismv = FALSE;
3324   gint64 initial_offset;
3325   gint32 min_ct = 0;
3326
3327   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3328       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3329       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3330       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3331
3332   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3333     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3334     return TRUE;
3335   }
3336
3337   /* presence of stss or not can't really tell us much,
3338    * and flags and so on tend to be marginally reliable in these files */
3339   if (stream->subtype == FOURCC_soun) {
3340     GST_DEBUG_OBJECT (qtdemux,
3341         "sound track in fragmented file; marking all keyframes");
3342     stream->all_keyframe = TRUE;
3343   }
3344
3345   if (!gst_byte_reader_get_uint8 (trun, &version) ||
3346       !gst_byte_reader_get_uint24_be (trun, &flags))
3347     goto fail;
3348
3349   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3350     goto fail;
3351
3352   if (flags & TR_DATA_OFFSET) {
3353     /* note this is really signed */
3354     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3355       goto fail;
3356     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3357     /* default base offset = first byte of moof */
3358     if (*base_offset == -1) {
3359       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3360       *base_offset = moof_offset;
3361     }
3362     *running_offset = *base_offset + data_offset;
3363   } else {
3364     /* if no offset at all, that would mean data starts at moof start,
3365      * which is a bit wrong and is ismv crappy way, so compensate
3366      * assuming data is in mdat following moof */
3367     if (*base_offset == -1) {
3368       *base_offset = moof_offset + moof_length + 8;
3369       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3370       ismv = TRUE;
3371     }
3372     if (*running_offset == -1)
3373       *running_offset = *base_offset;
3374   }
3375
3376   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3377       *running_offset);
3378   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3379       data_offset, flags, samples_count);
3380
3381   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3382     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3383       GST_DEBUG_OBJECT (qtdemux,
3384           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3385       flags ^= TR_FIRST_SAMPLE_FLAGS;
3386     } else {
3387       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3388         goto fail;
3389       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3390     }
3391   }
3392
3393   /* FIXME ? spec says other bits should also be checked to determine
3394    * entry size (and prefix size for that matter) */
3395   entry_size = 0;
3396   dur_offset = size_offset = 0;
3397   if (flags & TR_SAMPLE_DURATION) {
3398     GST_LOG_OBJECT (qtdemux, "entry duration present");
3399     dur_offset = entry_size;
3400     entry_size += 4;
3401   }
3402   if (flags & TR_SAMPLE_SIZE) {
3403     GST_LOG_OBJECT (qtdemux, "entry size present");
3404     size_offset = entry_size;
3405     entry_size += 4;
3406   }
3407   if (flags & TR_SAMPLE_FLAGS) {
3408     GST_LOG_OBJECT (qtdemux, "entry flags present");
3409     flags_offset = entry_size;
3410     entry_size += 4;
3411   }
3412   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3413     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3414     ct_offset = entry_size;
3415     entry_size += 4;
3416   }
3417
3418   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3419     goto fail;
3420   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3421
3422   if (stream->n_samples + samples_count >=
3423       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3424     goto index_too_big;
3425
3426   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3427       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3428       (stream->n_samples + samples_count) *
3429       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3430
3431   /* create a new array of samples if it's the first sample parsed */
3432   if (stream->n_samples == 0) {
3433     g_assert (stream->samples == NULL);
3434     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3435     /* or try to reallocate it with space enough to insert the new samples */
3436   } else
3437     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3438         stream->n_samples + samples_count);
3439   if (stream->samples == NULL)
3440     goto out_of_memory;
3441
3442   if (qtdemux->fragment_start != -1) {
3443     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3444     qtdemux->fragment_start = -1;
3445   } else {
3446     if (stream->n_samples == 0) {
3447       if (decode_ts > 0) {
3448         timestamp = decode_ts;
3449       } else if (stream->pending_seek != NULL) {
3450         /* if we don't have a timestamp from a tfdt box, we'll use the one
3451          * from the mfra seek table */
3452         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3453             GST_TIME_ARGS (stream->pending_seek->ts));
3454
3455         /* FIXME: this is not fully correct, the timestamp refers to the random
3456          * access sample refered to in the tfra entry, which may not necessarily
3457          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3458         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3459       } else {
3460         timestamp = 0;
3461       }
3462
3463       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3464       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3465           GST_TIME_ARGS (gst_ts));
3466     } else {
3467       /* subsequent fragments extend stream */
3468       timestamp =
3469           stream->samples[stream->n_samples - 1].timestamp +
3470           stream->samples[stream->n_samples - 1].duration;
3471
3472       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3473        * difference (1 sec.) between decode_ts and timestamp, prefer the
3474        * former */
3475       if (has_tfdt && !qtdemux->upstream_format_is_time
3476           && ABSDIFF (decode_ts, timestamp) >
3477           MAX (stream->duration_last_moof / 2,
3478               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3479         GST_INFO_OBJECT (qtdemux,
3480             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3481             ") are significantly different (more than %" GST_TIME_FORMAT
3482             "), using decode_ts",
3483             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3484             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3485             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3486                     MAX (stream->duration_last_moof / 2,
3487                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3488         timestamp = decode_ts;
3489       }
3490
3491       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3492       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3493           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3494     }
3495   }
3496
3497   initial_offset = *running_offset;
3498
3499   sample = stream->samples + stream->n_samples;
3500   for (i = 0; i < samples_count; i++) {
3501     guint32 dur, size, sflags;
3502     gint32 ct;
3503
3504     /* first read sample data */
3505     if (flags & TR_SAMPLE_DURATION) {
3506       dur = QT_UINT32 (data + dur_offset);
3507     } else {
3508       dur = d_sample_duration;
3509     }
3510     if (flags & TR_SAMPLE_SIZE) {
3511       size = QT_UINT32 (data + size_offset);
3512     } else {
3513       size = d_sample_size;
3514     }
3515     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3516       if (i == 0) {
3517         sflags = first_flags;
3518       } else {
3519         sflags = d_sample_flags;
3520       }
3521     } else if (flags & TR_SAMPLE_FLAGS) {
3522       sflags = QT_UINT32 (data + flags_offset);
3523     } else {
3524       sflags = d_sample_flags;
3525     }
3526
3527     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3528       /* Read offsets as signed numbers regardless of trun version as very
3529        * high offsets are unlikely and there are files out there that use
3530        * version=0 truns with negative offsets */
3531       ct = QT_UINT32 (data + ct_offset);
3532
3533       /* FIXME: Set offset to 0 for "no decode samples". This needs
3534        * to be handled in a codec specific manner ideally. */
3535       if (ct == G_MININT32)
3536         ct = 0;
3537     } else {
3538       ct = 0;
3539     }
3540     data += entry_size;
3541
3542     /* fill the sample information */
3543     sample->offset = *running_offset;
3544     sample->pts_offset = ct;
3545     sample->size = size;
3546     sample->timestamp = timestamp;
3547     sample->duration = dur;
3548     /* sample-is-difference-sample */
3549     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3550      * now idea how it relates to bitfield other than massive LE/BE confusion */
3551     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3552     *running_offset += size;
3553     timestamp += dur;
3554     stream->duration_moof += dur;
3555     sample++;
3556
3557     if (ct < min_ct)
3558       min_ct = ct;
3559   }
3560
3561   /* Shift PTS/DTS to allow for negative composition offsets while keeping
3562    * A/V sync in place. This is similar to the code handling ctts/cslg in the
3563    * non-fragmented case.
3564    */
3565   if (min_ct < 0)
3566     stream->cslg_shift = -min_ct;
3567   else
3568     stream->cslg_shift = 0;
3569
3570   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
3571       stream->cslg_shift);
3572
3573   /* Update total duration if needed */
3574   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3575
3576   /* Pre-emptively figure out size of mdat based on trun information.
3577    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3578    * size, else we will still be able to use this when dealing with gap'ed
3579    * input */
3580   qtdemux->mdatleft = *running_offset - initial_offset;
3581   qtdemux->mdatoffset = initial_offset;
3582   qtdemux->mdatsize = qtdemux->mdatleft;
3583
3584   stream->n_samples += samples_count;
3585   stream->n_samples_moof += samples_count;
3586
3587   if (stream->pending_seek != NULL)
3588     stream->pending_seek = NULL;
3589
3590   return TRUE;
3591
3592 fail:
3593   {
3594     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3595     return FALSE;
3596   }
3597 out_of_memory:
3598   {
3599     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3600         stream->n_samples);
3601     return FALSE;
3602   }
3603 index_too_big:
3604   {
3605     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3606         "be larger than %uMB (broken file?)", stream->n_samples,
3607         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3608     return FALSE;
3609   }
3610 }
3611
3612 /* find stream with @id */
3613 static inline QtDemuxStream *
3614 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3615 {
3616   QtDemuxStream *stream;
3617   gint i;
3618
3619   /* check */
3620   if (G_UNLIKELY (!id)) {
3621     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3622     return NULL;
3623   }
3624
3625   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3626     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3627     if (stream->track_id == id)
3628       return stream;
3629   }
3630   if (qtdemux->mss_mode) {
3631     /* mss should have only 1 stream anyway */
3632     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3633   }
3634
3635   return NULL;
3636 }
3637
3638 static gboolean
3639 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3640     guint32 * fragment_number)
3641 {
3642   if (!gst_byte_reader_skip (mfhd, 4))
3643     goto fail;
3644   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3645     goto fail;
3646   return TRUE;
3647 fail:
3648   {
3649     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3650     return FALSE;
3651   }
3652 }
3653
3654 static gboolean
3655 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3656     QtDemuxStream ** stream, guint32 * default_sample_duration,
3657     guint32 * default_sample_size, guint32 * default_sample_flags,
3658     gint64 * base_offset)
3659 {
3660   guint32 flags = 0;
3661   guint32 track_id = 0;
3662
3663   if (!gst_byte_reader_skip (tfhd, 1) ||
3664       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3665     goto invalid_track;
3666
3667   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3668     goto invalid_track;
3669
3670   *stream = qtdemux_find_stream (qtdemux, track_id);
3671   if (G_UNLIKELY (!*stream))
3672     goto unknown_stream;
3673
3674   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3675     *base_offset = qtdemux->moof_offset;
3676
3677   if (flags & TF_BASE_DATA_OFFSET)
3678     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3679       goto invalid_track;
3680
3681   /* obtain stream defaults */
3682   if (qtdemux_parse_trex (qtdemux, *stream,
3683           default_sample_duration, default_sample_size, default_sample_flags)) {
3684
3685     /* Default sample description index is only valid if trex parsing succeeded */
3686     (*stream)->stsd_sample_description_id =
3687         (*stream)->def_sample_description_index - 1;
3688   }
3689
3690   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3691     guint32 sample_description_index;
3692     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3693       goto invalid_track;
3694     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3695   }
3696
3697   if (qtdemux->mss_mode) {
3698     /* mss has no stsd entry */
3699     (*stream)->stsd_sample_description_id = 0;
3700   }
3701
3702   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3703     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3704       goto invalid_track;
3705
3706   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3707     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3708       goto invalid_track;
3709
3710   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3711     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3712       goto invalid_track;
3713
3714   return TRUE;
3715
3716 invalid_track:
3717   {
3718     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3719     return FALSE;
3720   }
3721 unknown_stream:
3722   {
3723     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3724     return TRUE;
3725   }
3726 }
3727
3728 static gboolean
3729 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3730     guint64 * decode_time)
3731 {
3732   guint32 version = 0;
3733
3734   if (!gst_byte_reader_get_uint32_be (br, &version))
3735     return FALSE;
3736
3737   version >>= 24;
3738   if (version == 1) {
3739     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3740       goto failed;
3741   } else {
3742     guint32 dec_time = 0;
3743     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3744       goto failed;
3745     *decode_time = dec_time;
3746   }
3747
3748   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3749       *decode_time);
3750
3751   return TRUE;
3752
3753 failed:
3754   {
3755     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3756     return FALSE;
3757   }
3758 }
3759
3760 /* Returns a pointer to a GstStructure containing the properties of
3761  * the stream sample identified by @sample_index. The caller must unref
3762  * the returned object after use. Returns NULL if unsuccessful. */
3763 static GstStructure *
3764 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3765     QtDemuxStream * stream, guint sample_index)
3766 {
3767   QtDemuxCencSampleSetInfo *info = NULL;
3768
3769   g_return_val_if_fail (stream != NULL, NULL);
3770   g_return_val_if_fail (stream->protected, NULL);
3771   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3772
3773   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3774
3775   /* Currently, cenc properties for groups of samples are not supported, so
3776    * simply return a copy of the default sample properties */
3777   return gst_structure_copy (info->default_properties);
3778 }
3779
3780 /* Parses the sizes of sample auxiliary information contained within a stream,
3781  * as given in a saiz box. Returns array of sample_count guint8 size values,
3782  * or NULL on failure */
3783 static guint8 *
3784 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3785     GstByteReader * br, guint32 * sample_count)
3786 {
3787   guint32 flags = 0;
3788   guint8 *info_sizes;
3789   guint8 default_info_size;
3790
3791   g_return_val_if_fail (qtdemux != NULL, NULL);
3792   g_return_val_if_fail (stream != NULL, NULL);
3793   g_return_val_if_fail (br != NULL, NULL);
3794   g_return_val_if_fail (sample_count != NULL, NULL);
3795
3796   if (!gst_byte_reader_get_uint32_be (br, &flags))
3797     return NULL;
3798
3799   if (flags & 0x1) {
3800     /* aux_info_type and aux_info_type_parameter are ignored */
3801     if (!gst_byte_reader_skip (br, 8))
3802       return NULL;
3803   }
3804
3805   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3806     return NULL;
3807   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3808
3809   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3810     return NULL;
3811   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3812
3813
3814   if (default_info_size == 0) {
3815     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3816       return NULL;
3817     }
3818   } else {
3819     info_sizes = g_new (guint8, *sample_count);
3820     memset (info_sizes, default_info_size, *sample_count);
3821   }
3822
3823   return info_sizes;
3824 }
3825
3826 /* Parses the offset of sample auxiliary information contained within a stream,
3827  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3828 static gboolean
3829 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3830     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3831     guint64 * offset)
3832 {
3833   guint8 version = 0;
3834   guint32 flags = 0;
3835   guint32 aux_info_type = 0;
3836   guint32 aux_info_type_parameter = 0;
3837   guint32 entry_count;
3838   guint32 off_32;
3839   guint64 off_64;
3840   const guint8 *aux_info_type_data = NULL;
3841
3842   g_return_val_if_fail (qtdemux != NULL, FALSE);
3843   g_return_val_if_fail (stream != NULL, FALSE);
3844   g_return_val_if_fail (br != NULL, FALSE);
3845   g_return_val_if_fail (offset != NULL, FALSE);
3846
3847   if (!gst_byte_reader_get_uint8 (br, &version))
3848     return FALSE;
3849
3850   if (!gst_byte_reader_get_uint24_be (br, &flags))
3851     return FALSE;
3852
3853   if (flags & 0x1) {
3854
3855     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3856       return FALSE;
3857     aux_info_type = QT_FOURCC (aux_info_type_data);
3858
3859     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3860       return FALSE;
3861   } else if (stream->protected) {
3862     aux_info_type = stream->protection_scheme_type;
3863   } else {
3864     aux_info_type = CUR_STREAM (stream)->fourcc;
3865   }
3866
3867   if (info_type)
3868     *info_type = aux_info_type;
3869   if (info_type_parameter)
3870     *info_type_parameter = aux_info_type_parameter;
3871
3872   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3873       "aux_info_type_parameter:  %#06x",
3874       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3875
3876   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3877     return FALSE;
3878
3879   if (entry_count != 1) {
3880     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3881     return FALSE;
3882   }
3883
3884   if (version == 0) {
3885     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3886       return FALSE;
3887     *offset = (guint64) off_32;
3888   } else {
3889     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3890       return FALSE;
3891     *offset = off_64;
3892   }
3893
3894   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3895   return TRUE;
3896 }
3897
3898 static void
3899 qtdemux_gst_structure_free (GstStructure * gststructure)
3900 {
3901   if (gststructure) {
3902     gst_structure_free (gststructure);
3903   }
3904 }
3905
3906 /* Parses auxiliary information relating to samples protected using
3907  * Common Encryption (cenc); the format of this information
3908  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3909  * otherwise. */
3910 static gboolean
3911 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3912     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3913 {
3914   QtDemuxCencSampleSetInfo *ss_info = NULL;
3915   guint8 size;
3916   gint i;
3917   GPtrArray *old_crypto_info = NULL;
3918   guint old_entries = 0;
3919
3920   g_return_val_if_fail (qtdemux != NULL, FALSE);
3921   g_return_val_if_fail (stream != NULL, FALSE);
3922   g_return_val_if_fail (br != NULL, FALSE);
3923   g_return_val_if_fail (stream->protected, FALSE);
3924   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3925
3926   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3927
3928   if (ss_info->crypto_info) {
3929     old_crypto_info = ss_info->crypto_info;
3930     /* Count number of non-null entries remaining at the tail end */
3931     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3932       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3933         break;
3934       old_entries++;
3935     }
3936   }
3937
3938   ss_info->crypto_info =
3939       g_ptr_array_new_full (sample_count + old_entries,
3940       (GDestroyNotify) qtdemux_gst_structure_free);
3941
3942   /* We preserve old entries because we parse the next moof in advance
3943    * of consuming all samples from the previous moof, and otherwise
3944    * we'd discard the corresponding crypto info for the samples
3945    * from the previous fragment. */
3946   if (old_entries) {
3947     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3948         old_entries);
3949     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3950       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3951               i));
3952       g_ptr_array_index (old_crypto_info, i) = NULL;
3953     }
3954   }
3955
3956   if (old_crypto_info) {
3957     /* Everything now belongs to the new array */
3958     g_ptr_array_free (old_crypto_info, TRUE);
3959   }
3960
3961   for (i = 0; i < sample_count; ++i) {
3962     GstStructure *properties;
3963     guint16 n_subsamples = 0;
3964     guint8 *data;
3965     guint iv_size;
3966     GstBuffer *buf;
3967     gboolean could_read_iv;
3968
3969     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3970     if (properties == NULL) {
3971       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3972       return FALSE;
3973     }
3974     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3975       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3976       gst_structure_free (properties);
3977       return FALSE;
3978     }
3979     could_read_iv =
3980         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3981     if (could_read_iv) {
3982       buf = gst_buffer_new_wrapped (data, iv_size);
3983       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3984       gst_buffer_unref (buf);
3985     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3986       const GValue *constant_iv_size_value =
3987           gst_structure_get_value (properties, "constant_iv_size");
3988       const GValue *constant_iv_value =
3989           gst_structure_get_value (properties, "iv");
3990       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3991         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3992         gst_structure_free (properties);
3993         return FALSE;
3994       }
3995       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3996       gst_structure_remove_field (properties, "constant_iv_size");
3997     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3998       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3999       gst_structure_free (properties);
4000       return FALSE;
4001     }
4002     size = info_sizes[i];
4003     if (size > iv_size) {
4004       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
4005           || !(n_subsamples > 0)) {
4006         gst_structure_free (properties);
4007         GST_ERROR_OBJECT (qtdemux,
4008             "failed to get subsample count for sample %u", i);
4009         return FALSE;
4010       }
4011       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
4012       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
4013         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
4014             i);
4015         gst_structure_free (properties);
4016         return FALSE;
4017       }
4018       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
4019       if (!buf) {
4020         gst_structure_free (properties);
4021         return FALSE;
4022       }
4023       gst_structure_set (properties,
4024           "subsample_count", G_TYPE_UINT, n_subsamples,
4025           "subsamples", GST_TYPE_BUFFER, buf, NULL);
4026       gst_buffer_unref (buf);
4027     } else {
4028       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
4029     }
4030     g_ptr_array_add (ss_info->crypto_info, properties);
4031   }
4032   return TRUE;
4033 }
4034
4035 /* Converts a UUID in raw byte form to a string representation, as defined in
4036  * RFC 4122. The caller takes ownership of the returned string and is
4037  * responsible for freeing it after use. */
4038 static gchar *
4039 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4040 {
4041   const guint8 *uuid = (const guint8 *) uuid_bytes;
4042
4043   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4044       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4045       uuid[0], uuid[1], uuid[2], uuid[3],
4046       uuid[4], uuid[5], uuid[6], uuid[7],
4047       uuid[8], uuid[9], uuid[10], uuid[11],
4048       uuid[12], uuid[13], uuid[14], uuid[15]);
4049 }
4050
4051 /* Parses a Protection System Specific Header box (pssh), as defined in the
4052  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4053  * information needed by a specific content protection system in order to
4054  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4055  * otherwise. */
4056 static gboolean
4057 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4058 {
4059   gchar *sysid_string;
4060   guint32 pssh_size = QT_UINT32 (node->data);
4061   GstBuffer *pssh = NULL;
4062   GstEvent *event = NULL;
4063   guint32 parent_box_type;
4064   gint i;
4065
4066   if (G_UNLIKELY (pssh_size < 32U)) {
4067     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4068     return FALSE;
4069   }
4070
4071   sysid_string =
4072       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4073
4074   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4075
4076   pssh = gst_buffer_new_memdup (node->data, pssh_size);
4077   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4078       gst_buffer_get_size (pssh));
4079
4080   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4081
4082   /* Push an event containing the pssh box onto the queues of all streams. */
4083   event = gst_event_new_protection (sysid_string, pssh,
4084       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4085   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4086     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4087     GST_TRACE_OBJECT (qtdemux,
4088         "adding protection event for stream %s and system %s",
4089         stream->stream_id, sysid_string);
4090     g_queue_push_tail (&stream->protection_scheme_event_queue,
4091         gst_event_ref (event));
4092   }
4093   g_free (sysid_string);
4094   gst_event_unref (event);
4095   gst_buffer_unref (pssh);
4096   return TRUE;
4097 }
4098
4099 static gboolean
4100 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4101     guint64 moof_offset, QtDemuxStream * stream)
4102 {
4103   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4104   GNode *uuid_node;
4105   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4106   GNode *saiz_node, *saio_node, *pssh_node;
4107   GstByteReader saiz_data, saio_data;
4108   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4109   gint64 base_offset, running_offset;
4110   guint32 frag_num;
4111   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4112
4113   /* NOTE @stream ignored */
4114
4115   moof_node = g_node_new ((guint8 *) buffer);
4116   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4117   qtdemux_node_dump (qtdemux, moof_node);
4118
4119   /* Get fragment number from mfhd and check it's valid */
4120   mfhd_node =
4121       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4122   if (mfhd_node == NULL)
4123     goto missing_mfhd;
4124   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4125     goto fail;
4126   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4127
4128   /* unknown base_offset to start with */
4129   base_offset = running_offset = -1;
4130   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4131   while (traf_node) {
4132     guint64 decode_time = 0;
4133
4134     /* Fragment Header node */
4135     tfhd_node =
4136         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4137         &tfhd_data);
4138     if (!tfhd_node)
4139       goto missing_tfhd;
4140     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4141             &ds_size, &ds_flags, &base_offset))
4142       goto missing_tfhd;
4143
4144     /* The following code assumes at most a single set of sample auxiliary
4145      * data in the fragment (consisting of a saiz box and a corresponding saio
4146      * box); in theory, however, there could be multiple sets of sample
4147      * auxiliary data in a fragment. */
4148     saiz_node =
4149         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4150         &saiz_data);
4151     if (saiz_node) {
4152       guint32 info_type = 0;
4153       guint64 offset = 0;
4154       guint32 info_type_parameter = 0;
4155
4156       g_free (qtdemux->cenc_aux_info_sizes);
4157
4158       qtdemux->cenc_aux_info_sizes =
4159           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4160           &qtdemux->cenc_aux_sample_count);
4161       if (qtdemux->cenc_aux_info_sizes == NULL) {
4162         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4163         goto fail;
4164       }
4165       saio_node =
4166           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4167           &saio_data);
4168       if (!saio_node) {
4169         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4170         g_free (qtdemux->cenc_aux_info_sizes);
4171         qtdemux->cenc_aux_info_sizes = NULL;
4172         goto fail;
4173       }
4174
4175       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4176                   &info_type, &info_type_parameter, &offset))) {
4177         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4178         g_free (qtdemux->cenc_aux_info_sizes);
4179         qtdemux->cenc_aux_info_sizes = NULL;
4180         goto fail;
4181       }
4182       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4183         offset += (guint64) (base_offset - qtdemux->moof_offset);
4184       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4185           && info_type_parameter == 0U) {
4186         GstByteReader br;
4187         if (offset > length) {
4188           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4189           qtdemux->cenc_aux_info_offset = offset;
4190         } else {
4191           gst_byte_reader_init (&br, buffer + offset, length - offset);
4192           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4193                   qtdemux->cenc_aux_info_sizes,
4194                   qtdemux->cenc_aux_sample_count)) {
4195             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4196             g_free (qtdemux->cenc_aux_info_sizes);
4197             qtdemux->cenc_aux_info_sizes = NULL;
4198             goto fail;
4199           }
4200         }
4201       }
4202     }
4203
4204     tfdt_node =
4205         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4206         &tfdt_data);
4207     if (tfdt_node) {
4208       /* We'll use decode_time to interpolate timestamps
4209        * in case the input timestamps are missing */
4210       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4211
4212       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4213           " (%" GST_TIME_FORMAT ")", decode_time,
4214           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4215                   decode_time) : GST_CLOCK_TIME_NONE));
4216
4217       /* Discard the fragment buffer timestamp info to avoid using it.
4218        * Rely on tfdt instead as it is more accurate than the timestamp
4219        * that is fetched from a manifest/playlist and is usually
4220        * less accurate. */
4221       qtdemux->fragment_start = -1;
4222     }
4223
4224     if (G_UNLIKELY (!stream)) {
4225       /* we lost track of offset, we'll need to regain it,
4226        * but can delay complaining until later or avoid doing so altogether */
4227       base_offset = -2;
4228       goto next;
4229     }
4230     if (G_UNLIKELY (base_offset < -1))
4231       goto lost_offset;
4232
4233     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4234
4235     if (!qtdemux->pullbased) {
4236       /* Sample tables can grow enough to be problematic if the system memory
4237        * is very low (e.g. embedded devices) and the videos very long
4238        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4239        * Fortunately, we can easily discard them for each new fragment when
4240        * we know qtdemux will not receive seeks outside of the current fragment.
4241        * adaptivedemux honors this assumption.
4242        * This optimization is also useful for applications that use qtdemux as
4243        * a push-based simple demuxer, like Media Source Extensions. */
4244       gst_qtdemux_stream_flush_samples_data (stream);
4245     }
4246
4247     /* initialise moof sample data */
4248     stream->n_samples_moof = 0;
4249     stream->duration_last_moof = stream->duration_moof;
4250     stream->duration_moof = 0;
4251
4252     /* Track Run node */
4253     trun_node =
4254         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4255         &trun_data);
4256     while (trun_node) {
4257       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4258           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4259           &running_offset, decode_time, (tfdt_node != NULL));
4260       /* iterate all siblings */
4261       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4262           &trun_data);
4263       /* don't use tfdt for subsequent trun as it only refers to the first */
4264       tfdt_node = NULL;
4265     }
4266
4267     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4268     if (uuid_node) {
4269       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4270       guint32 box_length = QT_UINT32 (uuid_buffer);
4271
4272       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4273     }
4274
4275     /* if no new base_offset provided for next traf,
4276      * base is end of current traf */
4277     base_offset = running_offset;
4278     running_offset = -1;
4279
4280     if (stream->n_samples_moof && stream->duration_moof)
4281       stream->new_caps = TRUE;
4282
4283   next:
4284     /* iterate all siblings */
4285     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4286   }
4287
4288   /* parse any protection system info */
4289   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4290   while (pssh_node) {
4291     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4292     qtdemux_parse_pssh (qtdemux, pssh_node);
4293     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4294   }
4295
4296   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4297       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4298       && min_dts != 0) {
4299     /* Unless the user has explicitly requested another seek, perform an
4300      * internal seek to the time specified in the tfdt.
4301      *
4302      * This way if the user opens a file where the first tfdt is 1 hour
4303      * into the presentation, they will not have to wait 1 hour for run
4304      * time to catch up and actual playback to start. */
4305     gint i;
4306
4307     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4308         "performing an internal seek to %" GST_TIME_FORMAT,
4309         GST_TIME_ARGS (min_dts));
4310
4311     qtdemux->segment.start = min_dts;
4312     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4313
4314     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4315       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4316       stream->time_position = min_dts;
4317     }
4318
4319     /* Before this code was run a segment was already sent when the moov was
4320      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4321      * be emitted after a moov, and we can emit a second segment anyway for
4322      * special cases like this. */
4323     qtdemux->need_segment = TRUE;
4324   }
4325
4326   qtdemux->first_moof_already_parsed = TRUE;
4327
4328   g_node_destroy (moof_node);
4329   return TRUE;
4330
4331 missing_tfhd:
4332   {
4333     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4334     goto fail;
4335   }
4336 missing_mfhd:
4337   {
4338     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4339     goto fail;
4340   }
4341 lost_offset:
4342   {
4343     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4344     goto fail;
4345   }
4346 fail:
4347   {
4348     g_node_destroy (moof_node);
4349     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4350         (_("This file is corrupt and cannot be played.")), (NULL));
4351     return FALSE;
4352   }
4353 }
4354
4355 #if 0
4356 /* might be used if some day we actually use mfra & co
4357  * for random access to fragments,
4358  * but that will require quite some modifications and much less relying
4359  * on a sample array */
4360 #endif
4361
4362 static gboolean
4363 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4364 {
4365   QtDemuxStream *stream;
4366   guint32 ver_flags, track_id, len, num_entries, i;
4367   guint value_size, traf_size, trun_size, sample_size;
4368   guint64 time = 0, moof_offset = 0;
4369 #if 0
4370   GstBuffer *buf = NULL;
4371   GstFlowReturn ret;
4372 #endif
4373   GstByteReader tfra;
4374
4375   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4376
4377   if (!gst_byte_reader_skip (&tfra, 8))
4378     return FALSE;
4379
4380   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4381     return FALSE;
4382
4383   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4384       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4385       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4386     return FALSE;
4387
4388   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4389
4390   stream = qtdemux_find_stream (qtdemux, track_id);
4391   if (stream == NULL)
4392     goto unknown_trackid;
4393
4394   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4395   sample_size = (len & 3) + 1;
4396   trun_size = ((len & 12) >> 2) + 1;
4397   traf_size = ((len & 48) >> 4) + 1;
4398
4399   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4400       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4401
4402   if (num_entries == 0)
4403     goto no_samples;
4404
4405   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4406           value_size + value_size + traf_size + trun_size + sample_size))
4407     goto corrupt_file;
4408
4409   g_free (stream->ra_entries);
4410   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4411   stream->n_ra_entries = num_entries;
4412
4413   for (i = 0; i < num_entries; i++) {
4414     qt_atom_parser_get_offset (&tfra, value_size, &time);
4415     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4416     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4417     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4418     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4419
4420     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4421
4422     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4423         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4424
4425     stream->ra_entries[i].ts = time;
4426     stream->ra_entries[i].moof_offset = moof_offset;
4427
4428     /* don't want to go through the entire file and read all moofs at startup */
4429 #if 0
4430     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4431     if (ret != GST_FLOW_OK)
4432       goto corrupt_file;
4433     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4434         moof_offset, stream);
4435     gst_buffer_unref (buf);
4436 #endif
4437   }
4438
4439   check_update_duration (qtdemux, time);
4440
4441   return TRUE;
4442
4443 /* ERRORS */
4444 unknown_trackid:
4445   {
4446     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4447     return FALSE;
4448   }
4449 corrupt_file:
4450   {
4451     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4452     return FALSE;
4453   }
4454 no_samples:
4455   {
4456     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4457     return FALSE;
4458   }
4459 }
4460
4461 static gboolean
4462 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4463 {
4464   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4465   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4466   GstBuffer *mfro = NULL, *mfra = NULL;
4467   GstFlowReturn flow;
4468   gboolean ret = FALSE;
4469   GNode *mfra_node, *tfra_node;
4470   guint64 mfra_offset = 0;
4471   guint32 fourcc, mfra_size;
4472   gint64 len;
4473
4474   /* query upstream size in bytes */
4475   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4476     goto size_query_failed;
4477
4478   /* mfro box should be at the very end of the file */
4479   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4480   if (flow != GST_FLOW_OK)
4481     goto exit;
4482
4483   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4484
4485   fourcc = QT_FOURCC (mfro_map.data + 4);
4486   if (fourcc != FOURCC_mfro)
4487     goto exit;
4488
4489   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4490   if (mfro_map.size < 16)
4491     goto invalid_mfro_size;
4492
4493   mfra_size = QT_UINT32 (mfro_map.data + 12);
4494   if (mfra_size >= len)
4495     goto invalid_mfra_size;
4496
4497   mfra_offset = len - mfra_size;
4498
4499   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4500       mfra_offset, mfra_size);
4501
4502   /* now get and parse mfra box */
4503   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4504   if (flow != GST_FLOW_OK)
4505     goto broken_file;
4506
4507   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4508
4509   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4510   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4511
4512   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4513
4514   while (tfra_node) {
4515     qtdemux_parse_tfra (qtdemux, tfra_node);
4516     /* iterate all siblings */
4517     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4518   }
4519   g_node_destroy (mfra_node);
4520
4521   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4522   ret = TRUE;
4523
4524 exit:
4525
4526   if (mfro) {
4527     if (mfro_map.memory != NULL)
4528       gst_buffer_unmap (mfro, &mfro_map);
4529     gst_buffer_unref (mfro);
4530   }
4531   if (mfra) {
4532     if (mfra_map.memory != NULL)
4533       gst_buffer_unmap (mfra, &mfra_map);
4534     gst_buffer_unref (mfra);
4535   }
4536   return ret;
4537
4538 /* ERRORS */
4539 size_query_failed:
4540   {
4541     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4542     goto exit;
4543   }
4544 invalid_mfro_size:
4545   {
4546     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4547     goto exit;
4548   }
4549 invalid_mfra_size:
4550   {
4551     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4552     goto exit;
4553   }
4554 broken_file:
4555   {
4556     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4557     goto exit;
4558   }
4559 }
4560
4561 static guint64
4562 add_offset (guint64 offset, guint64 advance)
4563 {
4564   /* Avoid 64-bit overflow by clamping */
4565   if (offset > G_MAXUINT64 - advance)
4566     return G_MAXUINT64;
4567   return offset + advance;
4568 }
4569
4570 static GstFlowReturn
4571 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4572 {
4573   guint64 length = 0;
4574   guint32 fourcc = 0;
4575   GstBuffer *buf = NULL;
4576   GstFlowReturn ret = GST_FLOW_OK;
4577   guint64 cur_offset = qtdemux->offset;
4578   GstMapInfo map;
4579
4580   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4581   if (G_UNLIKELY (ret != GST_FLOW_OK))
4582     goto beach;
4583   gst_buffer_map (buf, &map, GST_MAP_READ);
4584   if (G_LIKELY (map.size >= 8))
4585     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4586   gst_buffer_unmap (buf, &map);
4587   gst_buffer_unref (buf);
4588
4589   /* maybe we already got most we needed, so only consider this eof */
4590   if (G_UNLIKELY (length == 0)) {
4591     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4592         (_("Invalid atom size.")),
4593         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4594             GST_FOURCC_ARGS (fourcc)));
4595     ret = GST_FLOW_EOS;
4596     goto beach;
4597   }
4598
4599   switch (fourcc) {
4600     case FOURCC_moof:
4601       /* record for later parsing when needed */
4602       if (!qtdemux->moof_offset) {
4603         qtdemux->moof_offset = qtdemux->offset;
4604       }
4605       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4606         /* FIXME */
4607       } else {
4608         qtdemux->offset += length;      /* skip moof and keep going */
4609       }
4610       if (qtdemux->got_moov) {
4611         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4612         ret = GST_FLOW_EOS;
4613         goto beach;
4614       }
4615       break;
4616     case FOURCC_mdat:
4617     case FOURCC_free:
4618     case FOURCC_skip:
4619     case FOURCC_wide:
4620     case FOURCC_PICT:
4621     case FOURCC_pnot:
4622     {
4623       GST_LOG_OBJECT (qtdemux,
4624           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4625           GST_FOURCC_ARGS (fourcc), cur_offset);
4626       qtdemux->offset = add_offset (qtdemux->offset, length);
4627       break;
4628     }
4629     case FOURCC_moov:
4630     {
4631       GstBuffer *moov = NULL;
4632
4633       if (qtdemux->got_moov) {
4634         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4635         qtdemux->offset = add_offset (qtdemux->offset, length);
4636         goto beach;
4637       }
4638
4639       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4640       if (ret != GST_FLOW_OK)
4641         goto beach;
4642       gst_buffer_map (moov, &map, GST_MAP_READ);
4643
4644       if (length != map.size) {
4645         /* Some files have a 'moov' atom at the end of the file which contains
4646          * a terminal 'free' atom where the body of the atom is missing.
4647          * Check for, and permit, this special case.
4648          */
4649         if (map.size >= 8) {
4650           guint8 *final_data = map.data + (map.size - 8);
4651           guint32 final_length = QT_UINT32 (final_data);
4652           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4653
4654           if (final_fourcc == FOURCC_free
4655               && map.size + final_length - 8 == length) {
4656             /* Ok, we've found that special case. Allocate a new buffer with
4657              * that free atom actually present. */
4658             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4659             gst_buffer_fill (newmoov, 0, map.data, map.size);
4660             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4661             gst_buffer_unmap (moov, &map);
4662             gst_buffer_unref (moov);
4663             moov = newmoov;
4664             gst_buffer_map (moov, &map, GST_MAP_READ);
4665           }
4666         }
4667       }
4668
4669       if (length != map.size) {
4670         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4671             (_("This file is incomplete and cannot be played.")),
4672             ("We got less than expected (received %" G_GSIZE_FORMAT
4673                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4674                 (guint) length, cur_offset));
4675         gst_buffer_unmap (moov, &map);
4676         gst_buffer_unref (moov);
4677         ret = GST_FLOW_ERROR;
4678         goto beach;
4679       }
4680       qtdemux->offset += length;
4681
4682       qtdemux_parse_moov (qtdemux, map.data, length);
4683       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4684
4685       qtdemux_parse_tree (qtdemux);
4686       if (qtdemux->moov_node_compressed) {
4687         g_node_destroy (qtdemux->moov_node_compressed);
4688         g_free (qtdemux->moov_node->data);
4689       }
4690       qtdemux->moov_node_compressed = NULL;
4691       g_node_destroy (qtdemux->moov_node);
4692       qtdemux->moov_node = NULL;
4693       gst_buffer_unmap (moov, &map);
4694       gst_buffer_unref (moov);
4695       qtdemux->got_moov = TRUE;
4696
4697       break;
4698     }
4699     case FOURCC_ftyp:
4700     {
4701       GstBuffer *ftyp = NULL;
4702
4703       /* extract major brand; might come in handy for ISO vs QT issues */
4704       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4705       if (ret != GST_FLOW_OK)
4706         goto beach;
4707       qtdemux->offset += length;
4708       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4709       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4710       gst_buffer_unmap (ftyp, &map);
4711       gst_buffer_unref (ftyp);
4712       break;
4713     }
4714     case FOURCC_styp:
4715     {
4716       GstBuffer *styp = NULL;
4717
4718       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &styp);
4719       if (ret != GST_FLOW_OK)
4720         goto beach;
4721       qtdemux->offset += length;
4722       gst_buffer_map (styp, &map, GST_MAP_READ);
4723       qtdemux_parse_styp (qtdemux, map.data, map.size);
4724       gst_buffer_unmap (styp, &map);
4725       gst_buffer_unref (styp);
4726       break;
4727     }
4728     case FOURCC_uuid:
4729     {
4730       GstBuffer *uuid = NULL;
4731
4732       /* uuid are extension atoms */
4733       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4734       if (ret != GST_FLOW_OK)
4735         goto beach;
4736       qtdemux->offset += length;
4737       gst_buffer_map (uuid, &map, GST_MAP_READ);
4738       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4739       gst_buffer_unmap (uuid, &map);
4740       gst_buffer_unref (uuid);
4741       break;
4742     }
4743     case FOURCC_sidx:
4744     {
4745       GstBuffer *sidx = NULL;
4746       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4747       if (ret != GST_FLOW_OK)
4748         goto beach;
4749       qtdemux->offset += length;
4750       gst_buffer_map (sidx, &map, GST_MAP_READ);
4751       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4752       gst_buffer_unmap (sidx, &map);
4753       gst_buffer_unref (sidx);
4754       break;
4755     }
4756     case FOURCC_meta:
4757     {
4758       GstBuffer *meta = NULL;
4759       GNode *node, *child;
4760       GstByteReader child_data;
4761       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &meta);
4762       if (ret != GST_FLOW_OK)
4763         goto beach;
4764       qtdemux->offset += length;
4765       gst_buffer_map (meta, &map, GST_MAP_READ);
4766
4767       node = g_node_new (map.data);
4768
4769       qtdemux_parse_node (qtdemux, node, map.data, map.size);
4770
4771       /* Parse ONVIF Export File Format CorrectStartTime box if available */
4772       if ((child =
4773               qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
4774                   &child_data))) {
4775         qtdemux_parse_cstb (qtdemux, &child_data);
4776       }
4777
4778       g_node_destroy (node);
4779
4780       gst_buffer_unmap (meta, &map);
4781       gst_buffer_unref (meta);
4782       break;
4783     }
4784     default:
4785     {
4786       GstBuffer *unknown = NULL;
4787
4788       GST_LOG_OBJECT (qtdemux,
4789           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4790           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4791           cur_offset);
4792       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4793       if (ret != GST_FLOW_OK)
4794         goto beach;
4795       gst_buffer_map (unknown, &map, GST_MAP_READ);
4796       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4797       gst_buffer_unmap (unknown, &map);
4798       gst_buffer_unref (unknown);
4799       qtdemux->offset += length;
4800       break;
4801     }
4802   }
4803
4804 beach:
4805   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4806     /* digested all data, show what we have */
4807     qtdemux_prepare_streams (qtdemux);
4808     QTDEMUX_EXPOSE_LOCK (qtdemux);
4809     ret = qtdemux_expose_streams (qtdemux);
4810     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4811
4812     qtdemux->state = QTDEMUX_STATE_MOVIE;
4813     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4814         qtdemux->state);
4815     return ret;
4816   }
4817   return ret;
4818 }
4819
4820 /* Seeks to the previous keyframe of the indexed stream and
4821  * aligns other streams with respect to the keyframe timestamp
4822  * of indexed stream. Only called in case of Reverse Playback
4823  */
4824 static GstFlowReturn
4825 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4826 {
4827   guint32 seg_idx = 0, k_index = 0;
4828   guint32 ref_seg_idx, ref_k_index;
4829   GstClockTime k_pos = 0, last_stop = 0;
4830   QtDemuxSegment *seg = NULL;
4831   QtDemuxStream *ref_str = NULL;
4832   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4833   guint64 target_ts;
4834   gint i;
4835
4836   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4837    * and finally align all the other streams on that timestamp with their
4838    * respective keyframes */
4839   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4840     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4841
4842     /* No candidate yet, take the first stream */
4843     if (!ref_str) {
4844       ref_str = str;
4845       continue;
4846     }
4847
4848     /* So that stream has a segment, we prefer video streams */
4849     if (str->subtype == FOURCC_vide) {
4850       ref_str = str;
4851       break;
4852     }
4853   }
4854
4855   if (G_UNLIKELY (!ref_str)) {
4856     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4857     goto eos;
4858   }
4859
4860   if (G_UNLIKELY (!ref_str->from_sample)) {
4861     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4862     goto eos;
4863   }
4864
4865   /* So that stream has been playing from from_sample to to_sample. We will
4866    * get the timestamp of the previous sample and search for a keyframe before
4867    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4868   if (ref_str->subtype == FOURCC_vide) {
4869     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4870         ref_str->from_sample - 1, FALSE);
4871   } else {
4872     if (ref_str->from_sample >= 10)
4873       k_index = ref_str->from_sample - 10;
4874     else
4875       k_index = 0;
4876   }
4877
4878   target_ts =
4879       ref_str->samples[k_index].timestamp +
4880       ref_str->samples[k_index].pts_offset;
4881
4882   /* get current segment for that stream */
4883   seg = &ref_str->segments[ref_str->segment_index];
4884   /* Use segment start in original timescale for comparisons */
4885   seg_media_start_mov = seg->trak_media_start;
4886
4887   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4888       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4889       k_index, target_ts, seg_media_start_mov,
4890       GST_TIME_ARGS (seg->media_start));
4891
4892   /* Crawl back through segments to find the one containing this I frame */
4893   while (target_ts < seg_media_start_mov) {
4894     GST_DEBUG_OBJECT (qtdemux,
4895         "keyframe position (sample %u) is out of segment %u " " target %"
4896         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4897         ref_str->segment_index, target_ts, seg_media_start_mov);
4898
4899     if (G_UNLIKELY (!ref_str->segment_index)) {
4900       /* Reached first segment, let's consider it's EOS */
4901       goto eos;
4902     }
4903     ref_str->segment_index--;
4904     seg = &ref_str->segments[ref_str->segment_index];
4905     /* Use segment start in original timescale for comparisons */
4906     seg_media_start_mov = seg->trak_media_start;
4907   }
4908   /* Calculate time position of the keyframe and where we should stop */
4909   k_pos =
4910       QTSTREAMTIME_TO_GSTTIME (ref_str,
4911       target_ts - seg->trak_media_start) + seg->time;
4912   last_stop =
4913       QTSTREAMTIME_TO_GSTTIME (ref_str,
4914       ref_str->samples[ref_str->from_sample].timestamp -
4915       seg->trak_media_start) + seg->time;
4916
4917   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4918       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4919       k_index, GST_TIME_ARGS (k_pos));
4920
4921   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4922   qtdemux->segment.position = last_stop;
4923   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4924       GST_TIME_ARGS (last_stop));
4925
4926   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4927     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4928     goto eos;
4929   }
4930
4931   ref_seg_idx = ref_str->segment_index;
4932   ref_k_index = k_index;
4933
4934   /* Align them all on this */
4935   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4936     guint32 index = 0;
4937     GstClockTime seg_time = 0;
4938     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4939
4940     /* aligning reference stream again might lead to backing up to yet another
4941      * keyframe (due to timestamp rounding issues),
4942      * potentially putting more load on downstream; so let's try to avoid */
4943     if (str == ref_str) {
4944       seg_idx = ref_seg_idx;
4945       seg = &str->segments[seg_idx];
4946       k_index = ref_k_index;
4947       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4948           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4949     } else {
4950       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4951       GST_DEBUG_OBJECT (qtdemux,
4952           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4953           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4954
4955       /* get segment and time in the segment */
4956       seg = &str->segments[seg_idx];
4957       seg_time = k_pos - seg->time;
4958
4959       /* get the media time in the segment.
4960        * No adjustment for empty "filler" segments */
4961       if (seg->media_start != GST_CLOCK_TIME_NONE)
4962         seg_time += seg->media_start;
4963
4964       /* get the index of the sample with media time */
4965       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4966       GST_DEBUG_OBJECT (qtdemux,
4967           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4968           GST_TIME_ARGS (seg_time), index);
4969
4970       /* find previous keyframe */
4971       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4972     }
4973
4974     /* Remember until where we want to go */
4975     str->to_sample = str->from_sample - 1;
4976     /* Define our time position */
4977     target_ts =
4978         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4979     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4980     if (seg->media_start != GST_CLOCK_TIME_NONE)
4981       str->time_position -= seg->media_start;
4982
4983     /* Now seek back in time */
4984     gst_qtdemux_move_stream (qtdemux, str, k_index);
4985     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4986         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4987         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4988   }
4989
4990   return GST_FLOW_OK;
4991
4992 eos:
4993   return GST_FLOW_EOS;
4994 }
4995
4996 /*
4997  * Gets the current qt segment start, stop and position for the
4998  * given time offset. This is used in update_segment()
4999  */
5000 static void
5001 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
5002     QtDemuxStream * stream, GstClockTime offset,
5003     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
5004 {
5005   GstClockTime seg_time;
5006   GstClockTime start, stop, time;
5007   QtDemuxSegment *segment;
5008
5009   segment = &stream->segments[stream->segment_index];
5010
5011   /* get time in this segment */
5012   seg_time = (offset - segment->time) * segment->rate;
5013
5014   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
5015       GST_TIME_ARGS (seg_time));
5016
5017   if (G_UNLIKELY (seg_time > segment->duration)) {
5018     GST_LOG_OBJECT (stream->pad,
5019         "seg_time > segment->duration %" GST_TIME_FORMAT,
5020         GST_TIME_ARGS (segment->duration));
5021     seg_time = segment->duration;
5022   }
5023
5024   /* qtdemux->segment.stop is in outside-time-realm, whereas
5025    * segment->media_stop is in track-time-realm.
5026    *
5027    * In order to compare the two, we need to bring segment.stop
5028    * into the track-time-realm
5029    *
5030    * FIXME - does this comment still hold? Don't see any conversion here */
5031
5032   stop = qtdemux->segment.stop;
5033   if (stop == GST_CLOCK_TIME_NONE)
5034     stop = qtdemux->segment.duration;
5035   if (stop == GST_CLOCK_TIME_NONE)
5036     stop = segment->media_stop;
5037   else
5038     stop =
5039         MIN (segment->media_stop, stop - segment->time + segment->media_start);
5040
5041   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5042     start = segment->time + seg_time;
5043     time = offset;
5044     stop = start - seg_time + segment->duration;
5045   } else if (qtdemux->segment.rate >= 0) {
5046     start = MIN (segment->media_start + seg_time, stop);
5047     time = offset;
5048   } else {
5049     if (segment->media_start >= qtdemux->segment.start) {
5050       time = segment->time;
5051     } else {
5052       time = segment->time + (qtdemux->segment.start - segment->media_start);
5053     }
5054
5055     start = MAX (segment->media_start, qtdemux->segment.start);
5056     stop = MIN (segment->media_start + seg_time, stop);
5057   }
5058
5059   *_start = start;
5060   *_stop = stop;
5061   *_time = time;
5062 }
5063
5064 /*
5065  * Updates the qt segment used for the stream and pushes a new segment event
5066  * downstream on this stream's pad.
5067  */
5068 static gboolean
5069 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5070     gint seg_idx, GstClockTime offset, GstClockTime * _start,
5071     GstClockTime * _stop)
5072 {
5073   QtDemuxSegment *segment;
5074   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
5075   gdouble rate;
5076   GstEvent *event;
5077
5078   /* update the current segment */
5079   stream->segment_index = seg_idx;
5080
5081   /* get the segment */
5082   segment = &stream->segments[seg_idx];
5083
5084   if (G_UNLIKELY (offset < segment->time)) {
5085     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5086         GST_TIME_ARGS (segment->time));
5087     return FALSE;
5088   }
5089
5090   /* segment lies beyond total indicated duration */
5091   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5092           segment->time > qtdemux->segment.duration)) {
5093     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5094         " < segment->time %" GST_TIME_FORMAT,
5095         GST_TIME_ARGS (qtdemux->segment.duration),
5096         GST_TIME_ARGS (segment->time));
5097     return FALSE;
5098   }
5099
5100   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5101       &start, &stop, &time);
5102
5103   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5104       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5105       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5106
5107   /* combine global rate with that of the segment */
5108   rate = segment->rate * qtdemux->segment.rate;
5109
5110   /* Copy flags from main segment */
5111   stream->segment.flags = qtdemux->segment.flags;
5112
5113   /* update the segment values used for clipping */
5114   stream->segment.offset = qtdemux->segment.offset;
5115   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5116   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5117   stream->segment.rate = rate;
5118   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5119       stream->cslg_shift);
5120   if (stop != -1)
5121     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5122         stream->cslg_shift);
5123   else
5124     stream->segment.stop = stop;
5125   stream->segment.time = time;
5126   stream->segment.position = stream->segment.start;
5127
5128   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5129       &stream->segment);
5130
5131   /* now prepare and send the segment */
5132   if (stream->pad) {
5133     event = gst_event_new_segment (&stream->segment);
5134     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5135       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5136     }
5137     gst_pad_push_event (stream->pad, event);
5138     /* assume we can send more data now */
5139     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5140     /* clear to send tags on this pad now */
5141     gst_qtdemux_push_tags (qtdemux, stream);
5142   }
5143
5144   if (_start)
5145     *_start = start;
5146   if (_stop)
5147     *_stop = stop;
5148
5149   return TRUE;
5150 }
5151
5152 /* activate the given segment number @seg_idx of @stream at time @offset.
5153  * @offset is an absolute global position over all the segments.
5154  *
5155  * This will push out a NEWSEGMENT event with the right values and
5156  * position the stream index to the first decodable sample before
5157  * @offset.
5158  */
5159 static gboolean
5160 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5161     guint32 seg_idx, GstClockTime offset)
5162 {
5163   QtDemuxSegment *segment;
5164   guint32 index, kf_index;
5165   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5166
5167   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5168       seg_idx, GST_TIME_ARGS (offset));
5169
5170   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5171           &start, &stop))
5172     return FALSE;
5173
5174   segment = &stream->segments[stream->segment_index];
5175
5176   /* in the fragmented case, we pick a fragment that starts before our
5177    * desired position and rely on downstream to wait for a keyframe
5178    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5179    * tfra entries tells us which trun/sample the key unit is in, but we don't
5180    * make use of this additional information at the moment) */
5181   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5182     stream->to_sample = G_MAXUINT32;
5183     return TRUE;
5184   } else {
5185     /* well, it will be taken care of below */
5186     qtdemux->fragmented_seek_pending = FALSE;
5187     /* FIXME ideally the do_fragmented_seek can be done right here,
5188      * rather than at loop level
5189      * (which might even allow handling edit lists in a fragmented file) */
5190   }
5191
5192   /* We don't need to look for a sample in push-based */
5193   if (!qtdemux->pullbased)
5194     return TRUE;
5195
5196   /* and move to the keyframe before the indicated media time of the
5197    * segment */
5198   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5199     if (qtdemux->segment.rate >= 0) {
5200       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5201       stream->to_sample = G_MAXUINT32;
5202       GST_DEBUG_OBJECT (stream->pad,
5203           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5204           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5205           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5206     } else {
5207       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5208       stream->to_sample = index;
5209       GST_DEBUG_OBJECT (stream->pad,
5210           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5211           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5212           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5213     }
5214   } else {
5215     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5216         "this is an empty segment");
5217     return TRUE;
5218   }
5219
5220   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5221    * encountered an error and printed a message so we return appropriately */
5222   if (index == -1)
5223     return FALSE;
5224
5225   /* we're at the right spot */
5226   if (index == stream->sample_index) {
5227     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5228     return TRUE;
5229   }
5230
5231   /* find keyframe of the target index */
5232   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5233
5234   /* go back two frames to provide lead-in for non-raw audio decoders */
5235   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5236     guint32 lead_in = 2;
5237     guint32 old_index = kf_index;
5238     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5239
5240     if (gst_structure_has_name (s, "audio/mpeg")) {
5241       gint mpegversion;
5242       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5243           && mpegversion == 1) {
5244         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5245         lead_in = 30;
5246       }
5247     }
5248
5249     kf_index = MAX (kf_index, lead_in) - lead_in;
5250     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5251       GST_DEBUG_OBJECT (stream->pad,
5252           "Moving backwards %u frames to ensure sufficient sound lead-in",
5253           old_index - kf_index);
5254     } else {
5255       kf_index = old_index;
5256     }
5257   }
5258
5259   /* if we move forwards, we don't have to go back to the previous
5260    * keyframe since we already sent that. We can also just jump to
5261    * the keyframe right before the target index if there is one. */
5262   if (index > stream->sample_index) {
5263     /* moving forwards check if we move past a keyframe */
5264     if (kf_index > stream->sample_index) {
5265       GST_DEBUG_OBJECT (stream->pad,
5266           "moving forwards to keyframe at %u "
5267           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5268           kf_index,
5269           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5270           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5271       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5272     } else {
5273       GST_DEBUG_OBJECT (stream->pad,
5274           "moving forwards, keyframe at %u "
5275           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5276           kf_index,
5277           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5278           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5279     }
5280   } else {
5281     GST_DEBUG_OBJECT (stream->pad,
5282         "moving backwards to %sframe at %u "
5283         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5284         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5285         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5286         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5287     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5288   }
5289
5290   return TRUE;
5291 }
5292
5293 /* prepare to get the current sample of @stream, getting essential values.
5294  *
5295  * This function will also prepare and send the segment when needed.
5296  *
5297  * Return FALSE if the stream is EOS.
5298  *
5299  * PULL-BASED
5300  */
5301 static gboolean
5302 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5303     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5304     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5305     gboolean * keyframe)
5306 {
5307   QtDemuxSample *sample;
5308   GstClockTime time_position;
5309   guint32 seg_idx;
5310
5311   g_return_val_if_fail (stream != NULL, FALSE);
5312
5313   time_position = stream->time_position;
5314   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5315     goto eos;
5316
5317   seg_idx = stream->segment_index;
5318   if (G_UNLIKELY (seg_idx == -1)) {
5319     /* find segment corresponding to time_position if we are looking
5320      * for a segment. */
5321     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5322   }
5323
5324   /* different segment, activate it, sample_index will be set. */
5325   if (G_UNLIKELY (stream->segment_index != seg_idx))
5326     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5327
5328   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5329               segments[stream->segment_index]))) {
5330     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5331
5332     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5333         " prepare empty sample");
5334
5335     *empty = TRUE;
5336     *pts = *dts = time_position;
5337     *duration = seg->duration - (time_position - seg->time);
5338
5339     return TRUE;
5340   }
5341
5342   *empty = FALSE;
5343
5344   if (stream->sample_index == -1)
5345     stream->sample_index = 0;
5346
5347   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5348       stream->sample_index, stream->n_samples);
5349
5350   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5351     if (!qtdemux->fragmented)
5352       goto eos;
5353
5354     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5355     do {
5356       GstFlowReturn flow;
5357
5358       GST_OBJECT_LOCK (qtdemux);
5359       flow = qtdemux_add_fragmented_samples (qtdemux);
5360       GST_OBJECT_UNLOCK (qtdemux);
5361
5362       if (flow != GST_FLOW_OK)
5363         goto eos;
5364     }
5365     while (stream->sample_index >= stream->n_samples);
5366   }
5367
5368   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5369     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5370         stream->sample_index);
5371     return FALSE;
5372   }
5373
5374   /* now get the info for the sample we're at */
5375   sample = &stream->samples[stream->sample_index];
5376
5377   *dts = QTSAMPLE_DTS (stream, sample);
5378   *pts = QTSAMPLE_PTS (stream, sample);
5379   *offset = sample->offset;
5380   *size = sample->size;
5381   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5382   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5383
5384   return TRUE;
5385
5386   /* special cases */
5387 eos:
5388   {
5389     stream->time_position = GST_CLOCK_TIME_NONE;
5390     return FALSE;
5391   }
5392 }
5393
5394 /* move to the next sample in @stream.
5395  *
5396  * Moves to the next segment when needed.
5397  */
5398 static void
5399 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5400 {
5401   QtDemuxSample *sample;
5402   QtDemuxSegment *segment;
5403
5404   /* get current segment */
5405   segment = &stream->segments[stream->segment_index];
5406
5407   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5408     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5409     goto next_segment;
5410   }
5411
5412   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5413     /* Mark the stream as EOS */
5414     GST_DEBUG_OBJECT (qtdemux,
5415         "reached max allowed sample %u, mark EOS", stream->to_sample);
5416     stream->time_position = GST_CLOCK_TIME_NONE;
5417     return;
5418   }
5419
5420   /* move to next sample */
5421   stream->sample_index++;
5422   stream->offset_in_sample = 0;
5423
5424   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5425       stream->n_samples);
5426
5427   /* reached the last sample, we need the next segment */
5428   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5429     goto next_segment;
5430
5431   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5432     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5433         stream->sample_index);
5434     return;
5435   }
5436
5437   /* get next sample */
5438   sample = &stream->samples[stream->sample_index];
5439
5440   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5441       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5442       GST_TIME_ARGS (segment->media_stop));
5443
5444   /* see if we are past the segment */
5445   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5446     goto next_segment;
5447
5448   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5449     /* inside the segment, update time_position, looks very familiar to
5450      * GStreamer segments, doesn't it? */
5451     stream->time_position =
5452         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5453   } else {
5454     /* not yet in segment, time does not yet increment. This means
5455      * that we are still prerolling keyframes to the decoder so it can
5456      * decode the first sample of the segment. */
5457     stream->time_position = segment->time;
5458   }
5459   return;
5460
5461   /* move to the next segment */
5462 next_segment:
5463   {
5464     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5465
5466     if (stream->segment_index == stream->n_segments - 1) {
5467       /* are we at the end of the last segment, we're EOS */
5468       stream->time_position = GST_CLOCK_TIME_NONE;
5469     } else {
5470       /* else we're only at the end of the current segment */
5471       stream->time_position = segment->stop_time;
5472     }
5473     /* make sure we select a new segment */
5474
5475     /* accumulate previous segments */
5476     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5477       stream->accumulated_base +=
5478           (stream->segment.stop -
5479           stream->segment.start) / ABS (stream->segment.rate);
5480
5481     stream->segment_index = -1;
5482   }
5483 }
5484
5485 static void
5486 gst_qtdemux_sync_streams (GstQTDemux * demux)
5487 {
5488   gint i;
5489
5490   if (QTDEMUX_N_STREAMS (demux) <= 1)
5491     return;
5492
5493   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5494     QtDemuxStream *stream;
5495     GstClockTime end_time;
5496
5497     stream = QTDEMUX_NTH_STREAM (demux, i);
5498
5499     if (!stream->pad)
5500       continue;
5501
5502     /* TODO advance time on subtitle streams here, if any some day */
5503
5504     /* some clips/trailers may have unbalanced streams at the end,
5505      * so send EOS on shorter stream to prevent stalling others */
5506
5507     /* do not mess with EOS if SEGMENT seeking */
5508     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5509       continue;
5510
5511     if (demux->pullbased) {
5512       /* loop mode is sample time based */
5513       if (!STREAM_IS_EOS (stream))
5514         continue;
5515     } else {
5516       /* push mode is byte position based */
5517       if (stream->n_samples &&
5518           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5519         continue;
5520     }
5521
5522     if (stream->sent_eos)
5523       continue;
5524
5525     /* only act if some gap */
5526     end_time = stream->segments[stream->n_segments - 1].stop_time;
5527     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5528         ", stream end: %" GST_TIME_FORMAT,
5529         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5530     if (GST_CLOCK_TIME_IS_VALID (end_time)
5531         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5532       GstEvent *event;
5533
5534       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5535           GST_PAD_NAME (stream->pad));
5536       stream->sent_eos = TRUE;
5537       event = gst_event_new_eos ();
5538       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5539         gst_event_set_seqnum (event, demux->segment_seqnum);
5540       gst_pad_push_event (stream->pad, event);
5541     }
5542   }
5543 }
5544
5545 /* EOS and NOT_LINKED need to be combined. This means that we return:
5546  *
5547  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5548  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5549  */
5550 static GstFlowReturn
5551 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5552     GstFlowReturn ret)
5553 {
5554   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5555
5556   if (stream->pad)
5557     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5558         ret);
5559   else
5560     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5561
5562   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5563   return ret;
5564 }
5565
5566 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5567  * completely clipped
5568  *
5569  * Should be used only with raw buffers */
5570 static GstBuffer *
5571 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5572     GstBuffer * buf)
5573 {
5574   guint64 start, stop, cstart, cstop, diff;
5575   GstClockTime pts, duration;
5576   gsize size, osize;
5577   gint num_rate, denom_rate;
5578   gint frame_size;
5579   gboolean clip_data;
5580   guint offset;
5581
5582   osize = size = gst_buffer_get_size (buf);
5583   offset = 0;
5584
5585   /* depending on the type, setup the clip parameters */
5586   if (stream->subtype == FOURCC_soun) {
5587     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5588     num_rate = GST_SECOND;
5589     denom_rate = (gint) CUR_STREAM (stream)->rate;
5590     clip_data = TRUE;
5591   } else if (stream->subtype == FOURCC_vide) {
5592     frame_size = size;
5593     num_rate = CUR_STREAM (stream)->fps_n;
5594     denom_rate = CUR_STREAM (stream)->fps_d;
5595     clip_data = FALSE;
5596   } else
5597     goto wrong_type;
5598
5599   if (frame_size <= 0)
5600     goto bad_frame_size;
5601
5602   /* we can only clip if we have a valid pts */
5603   pts = GST_BUFFER_PTS (buf);
5604   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5605     goto no_pts;
5606
5607   duration = GST_BUFFER_DURATION (buf);
5608
5609   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5610     duration =
5611         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5612   }
5613
5614   start = pts;
5615   stop = start + duration;
5616
5617   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5618               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5619     goto clipped;
5620
5621   /* see if some clipping happened */
5622   diff = cstart - start;
5623   if (diff > 0) {
5624     pts += diff;
5625     duration -= diff;
5626
5627     if (clip_data) {
5628       /* bring clipped time to samples and to bytes */
5629       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5630       diff *= frame_size;
5631
5632       GST_DEBUG_OBJECT (qtdemux,
5633           "clipping start to %" GST_TIME_FORMAT " %"
5634           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5635
5636       offset = diff;
5637       size -= diff;
5638     }
5639   }
5640   diff = stop - cstop;
5641   if (diff > 0) {
5642     duration -= diff;
5643
5644     if (clip_data) {
5645       /* bring clipped time to samples and then to bytes */
5646       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5647       diff *= frame_size;
5648       GST_DEBUG_OBJECT (qtdemux,
5649           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5650           " bytes", GST_TIME_ARGS (cstop), diff);
5651       size -= diff;
5652     }
5653   }
5654
5655   if (offset != 0 || size != osize)
5656     gst_buffer_resize (buf, offset, size);
5657
5658   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5659   GST_BUFFER_PTS (buf) = pts;
5660   GST_BUFFER_DURATION (buf) = duration;
5661
5662   return buf;
5663
5664   /* dropped buffer */
5665 wrong_type:
5666   {
5667     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5668     return buf;
5669   }
5670 bad_frame_size:
5671   {
5672     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5673     return buf;
5674   }
5675 no_pts:
5676   {
5677     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5678     return buf;
5679   }
5680 clipped:
5681   {
5682     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5683     gst_buffer_unref (buf);
5684     return NULL;
5685   }
5686 }
5687
5688 static GstBuffer *
5689 gst_qtdemux_align_buffer (GstQTDemux * demux,
5690     GstBuffer * buffer, gsize alignment)
5691 {
5692   GstMapInfo map;
5693
5694   gst_buffer_map (buffer, &map, GST_MAP_READ);
5695
5696   if (map.size < sizeof (guintptr)) {
5697     gst_buffer_unmap (buffer, &map);
5698     return buffer;
5699   }
5700
5701   if (((guintptr) map.data) & (alignment - 1)) {
5702     GstBuffer *new_buffer;
5703     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5704
5705     new_buffer = gst_buffer_new_allocate (NULL,
5706         gst_buffer_get_size (buffer), &params);
5707
5708     /* Copy data "by hand", so ensure alignment is kept: */
5709     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5710
5711     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5712     GST_DEBUG_OBJECT (demux,
5713         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5714         alignment);
5715
5716     gst_buffer_unmap (buffer, &map);
5717     gst_buffer_unref (buffer);
5718
5719     return new_buffer;
5720   }
5721
5722   gst_buffer_unmap (buffer, &map);
5723   return buffer;
5724 }
5725
5726 static guint8 *
5727 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5728     gsize * res)
5729 {
5730   guint8 *storage;
5731   gsize i;
5732
5733   /* We are converting from pairs to triplets */
5734   *res = ccpair_size / 2 * 3;
5735   storage = g_malloc (*res);
5736   for (i = 0; i * 2 < ccpair_size; i += 1) {
5737     /* FIXME: Use line offset 0 as we simply can't know here */
5738     if (field == 1)
5739       storage[i * 3] = 0x80 | 0x00;
5740     else
5741       storage[i * 3] = 0x00 | 0x00;
5742     storage[i * 3 + 1] = ccpair[i * 2];
5743     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5744   }
5745
5746   return storage;
5747 }
5748
5749 static guint8 *
5750 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5751     gsize * cclen)
5752 {
5753   guint8 *res = NULL;
5754   guint32 atom_length, fourcc;
5755   QtDemuxStreamStsdEntry *stsd_entry;
5756
5757   GST_MEMDUMP ("caption atom", data, size);
5758
5759   /* There might be multiple atoms */
5760
5761   *cclen = 0;
5762   if (size < 8)
5763     goto invalid_cdat;
5764   atom_length = QT_UINT32 (data);
5765   fourcc = QT_FOURCC (data + 4);
5766   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5767     goto invalid_cdat;
5768
5769   GST_DEBUG_OBJECT (stream->pad, "here");
5770
5771   /* Check if we have something compatible */
5772   stsd_entry = CUR_STREAM (stream);
5773   switch (stsd_entry->fourcc) {
5774     case FOURCC_c608:{
5775       guint8 *cdat = NULL, *cdt2 = NULL;
5776       gsize cdat_size = 0, cdt2_size = 0;
5777       /* Should be cdat or cdt2 */
5778       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5779         GST_WARNING_OBJECT (stream->pad,
5780             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5781             GST_FOURCC_ARGS (fourcc));
5782         goto invalid_cdat;
5783       }
5784
5785       /* Convert to S334-1 Annex A byte triplet */
5786       if (fourcc == FOURCC_cdat)
5787         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5788       else
5789         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5790       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5791           size, atom_length);
5792
5793       /* Check for another atom ? */
5794       if (size > atom_length + 8) {
5795         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5796         if (size >= atom_length + new_atom_length) {
5797           fourcc = QT_FOURCC (data + atom_length + 4);
5798           if (fourcc == FOURCC_cdat) {
5799             if (cdat == NULL)
5800               cdat =
5801                   convert_to_s334_1a (data + atom_length + 8,
5802                   new_atom_length - 8, 1, &cdat_size);
5803             else
5804               GST_WARNING_OBJECT (stream->pad,
5805                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5806           } else {
5807             if (cdt2 == NULL)
5808               cdt2 =
5809                   convert_to_s334_1a (data + atom_length + 8,
5810                   new_atom_length - 8, 2, &cdt2_size);
5811             else
5812               GST_WARNING_OBJECT (stream->pad,
5813                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5814           }
5815         }
5816       }
5817
5818       *cclen = cdat_size + cdt2_size;
5819       res = g_malloc (*cclen);
5820       if (cdat_size)
5821         memcpy (res, cdat, cdat_size);
5822       if (cdt2_size)
5823         memcpy (res + cdat_size, cdt2, cdt2_size);
5824       g_free (cdat);
5825       g_free (cdt2);
5826     }
5827       break;
5828     case FOURCC_c708:
5829       if (fourcc != FOURCC_ccdp) {
5830         GST_WARNING_OBJECT (stream->pad,
5831             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5832             GST_FOURCC_ARGS (fourcc));
5833         goto invalid_cdat;
5834       }
5835       *cclen = atom_length - 8;
5836       res = g_memdup2 (data + 8, *cclen);
5837       break;
5838     default:
5839       /* Keep this here in case other closed caption formats are added */
5840       g_assert_not_reached ();
5841       break;
5842   }
5843
5844   GST_MEMDUMP ("Output", res, *cclen);
5845   return res;
5846
5847   /* Errors */
5848 invalid_cdat:
5849   GST_WARNING ("[cdat] atom is too small or invalid");
5850   return NULL;
5851 }
5852
5853 /* Handle Closed Caption sample buffers.
5854  * The input buffer metadata must be writable,
5855  * but time/duration etc not yet set and need not be preserved */
5856 static GstBuffer *
5857 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5858     GstBuffer * buf)
5859 {
5860   GstBuffer *outbuf = NULL;
5861   GstMapInfo map;
5862   guint8 *cc;
5863   gsize cclen = 0;
5864
5865   gst_buffer_map (buf, &map, GST_MAP_READ);
5866
5867   /* empty buffer is sent to terminate previous subtitle */
5868   if (map.size <= 2) {
5869     gst_buffer_unmap (buf, &map);
5870     gst_buffer_unref (buf);
5871     return NULL;
5872   }
5873
5874   /* For closed caption, we need to extract the information from the
5875    * [cdat],[cdt2] or [ccdp] atom */
5876   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5877   gst_buffer_unmap (buf, &map);
5878   if (cc) {
5879     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5880     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5881   } else {
5882     /* Conversion failed or there's nothing */
5883   }
5884   gst_buffer_unref (buf);
5885
5886   return outbuf;
5887 }
5888
5889 /* DVD subpicture specific sample handling.
5890  * the input buffer metadata must be writable,
5891  * but time/duration etc not yet set and need not be preserved */
5892 static GstBuffer *
5893 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5894     GstBuffer * buf)
5895 {
5896   /* send a one time dvd clut event */
5897   if (stream->pending_event && stream->pad)
5898     gst_pad_push_event (stream->pad, stream->pending_event);
5899   stream->pending_event = NULL;
5900
5901   /* empty buffer is sent to terminate previous subtitle */
5902   if (gst_buffer_get_size (buf) <= 2) {
5903     gst_buffer_unref (buf);
5904     return NULL;
5905   }
5906
5907   /* That's all the processing needed for subpictures */
5908   return buf;
5909 }
5910
5911 /* Timed text formats
5912  * the input buffer metadata must be writable,
5913  * but time/duration etc not yet set and need not be preserved */
5914 static GstBuffer *
5915 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5916     GstBuffer * buf)
5917 {
5918   GstBuffer *outbuf = NULL;
5919   GstMapInfo map;
5920   guint nsize = 0;
5921   gchar *str;
5922
5923   /* not many cases for now */
5924   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5925           stream->subtype != FOURCC_sbtl)) {
5926     return buf;
5927   }
5928
5929   gst_buffer_map (buf, &map, GST_MAP_READ);
5930
5931   /* empty buffer is sent to terminate previous subtitle */
5932   if (map.size <= 2) {
5933     gst_buffer_unmap (buf, &map);
5934     gst_buffer_unref (buf);
5935     return NULL;
5936   }
5937
5938   nsize = GST_READ_UINT16_BE (map.data);
5939   nsize = MIN (nsize, map.size - 2);
5940
5941   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5942       nsize, map.size);
5943
5944   /* takes care of UTF-8 validation or UTF-16 recognition,
5945    * no other encoding expected */
5946   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5947   gst_buffer_unmap (buf, &map);
5948
5949   if (str) {
5950     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5951     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5952   } else {
5953     /* this should not really happen unless the subtitle is corrupted */
5954   }
5955   gst_buffer_unref (buf);
5956
5957   /* FIXME ? convert optional subsequent style info to markup */
5958
5959   return outbuf;
5960 }
5961
5962 /* WebVTT sample handling according to 14496-30 */
5963 static GstBuffer *
5964 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5965     GstBuffer * buf)
5966 {
5967   GstBuffer *outbuf = NULL;
5968   GstMapInfo map;
5969
5970   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5971     g_assert_not_reached ();    /* The buffer must be mappable */
5972   }
5973
5974   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5975     GstEvent *gap = NULL;
5976     /* Push a gap event */
5977     stream->segment.position = GST_BUFFER_PTS (buf);
5978     gap =
5979         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5980     gst_pad_push_event (stream->pad, gap);
5981
5982     if (GST_BUFFER_DURATION_IS_VALID (buf))
5983       stream->segment.position += GST_BUFFER_DURATION (buf);
5984   } else {
5985     outbuf =
5986         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5987         GST_BUFFER_DURATION (buf), map.data, map.size);
5988     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5989   }
5990
5991   gst_buffer_unmap (buf, &map);
5992   gst_buffer_unref (buf);
5993
5994   return outbuf;
5995 }
5996
5997 static GstFlowReturn
5998 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5999     GstBuffer * buf)
6000 {
6001   GstFlowReturn ret = GST_FLOW_OK;
6002   GstClockTime pts, duration;
6003
6004   if (stream->need_clip)
6005     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
6006
6007   if (G_UNLIKELY (buf == NULL))
6008     goto exit;
6009
6010   if (G_UNLIKELY (stream->discont)) {
6011     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6012     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
6013     stream->discont = FALSE;
6014   } else {
6015     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6016   }
6017
6018   GST_LOG_OBJECT (qtdemux,
6019       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
6020       ", duration %" GST_TIME_FORMAT " on pad %s",
6021       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
6022       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
6023       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
6024
6025   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
6026     GstStructure *crypto_info;
6027     QtDemuxAavdEncryptionInfo *info =
6028         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
6029
6030     crypto_info = gst_structure_copy (info->default_properties);
6031     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6032       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
6033   }
6034
6035   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
6036           || stream->protection_scheme_type == FOURCC_cbcs)) {
6037     GstStructure *crypto_info;
6038     QtDemuxCencSampleSetInfo *info =
6039         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6040     gint index;
6041     GstEvent *event;
6042
6043     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
6044       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
6045           GST_PTR_FORMAT, event);
6046       gst_pad_push_event (stream->pad, event);
6047     }
6048
6049     if (info->crypto_info == NULL) {
6050       if (stream->protection_scheme_type == FOURCC_cbcs) {
6051         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
6052         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
6053           GST_ERROR_OBJECT (qtdemux,
6054               "failed to attach cbcs metadata to buffer");
6055           qtdemux_gst_structure_free (crypto_info);
6056         } else {
6057           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
6058         }
6059       } else {
6060         GST_DEBUG_OBJECT (qtdemux,
6061             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
6062       }
6063     } else {
6064       /* The end of the crypto_info array matches our n_samples position,
6065        * so count backward from there */
6066       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
6067       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
6068         /* steal structure from array */
6069         crypto_info = g_ptr_array_index (info->crypto_info, index);
6070         g_ptr_array_index (info->crypto_info, index) = NULL;
6071         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
6072             info->crypto_info->len);
6073         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
6074           GST_ERROR_OBJECT (qtdemux,
6075               "failed to attach cenc metadata to buffer");
6076       } else {
6077         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
6078             index, stream->sample_index);
6079       }
6080     }
6081   }
6082
6083   if (stream->alignment > 1)
6084     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
6085
6086   pts = GST_BUFFER_PTS (buf);
6087   duration = GST_BUFFER_DURATION (buf);
6088
6089   ret = gst_pad_push (stream->pad, buf);
6090
6091   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
6092     /* mark position in stream, we'll need this to know when to send GAP event */
6093     stream->segment.position = pts + duration;
6094   }
6095
6096 exit:
6097
6098   return ret;
6099 }
6100
6101 static GstFlowReturn
6102 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
6103     GstBuffer * buf)
6104 {
6105   GstFlowReturn ret = GST_FLOW_OK;
6106
6107   if (stream->subtype == FOURCC_clcp
6108       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
6109     GstMapInfo map;
6110     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
6111     guint n_triplets, i;
6112     guint field1_off = 0, field2_off = 0;
6113
6114     /* We have to split CEA608 buffers so that each outgoing buffer contains
6115      * one byte pair per field according to the framerate of the video track.
6116      *
6117      * If there is only a single byte pair per field we don't have to do
6118      * anything
6119      */
6120
6121     gst_buffer_map (buf, &map, GST_MAP_READ);
6122
6123     n_triplets = map.size / 3;
6124     for (i = 0; i < n_triplets; i++) {
6125       if (map.data[3 * i] & 0x80)
6126         n_field1++;
6127       else
6128         n_field2++;
6129     }
6130
6131     g_assert (n_field1 || n_field2);
6132
6133     /* If there's more than 1 frame we have to split, otherwise we can just
6134      * pass through */
6135     if (n_field1 > 1 || n_field2 > 1) {
6136       n_output_buffers =
6137           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
6138           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
6139
6140       for (i = 0; i < n_output_buffers; i++) {
6141         GstBuffer *outbuf =
6142             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
6143         GstMapInfo outmap;
6144         guint8 *outptr;
6145
6146         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
6147         outptr = outmap.data;
6148
6149         if (n_field1) {
6150           gboolean found = FALSE;
6151
6152           while (map.data + field1_off < map.data + map.size) {
6153             if (map.data[field1_off] & 0x80) {
6154               memcpy (outptr, &map.data[field1_off], 3);
6155               field1_off += 3;
6156               found = TRUE;
6157               break;
6158             }
6159             field1_off += 3;
6160           }
6161
6162           if (!found) {
6163             const guint8 empty[] = { 0x80, 0x80, 0x80 };
6164
6165             memcpy (outptr, empty, 3);
6166           }
6167
6168           outptr += 3;
6169         }
6170
6171         if (n_field2) {
6172           gboolean found = FALSE;
6173
6174           while (map.data + field2_off < map.data + map.size) {
6175             if ((map.data[field2_off] & 0x80) == 0) {
6176               memcpy (outptr, &map.data[field2_off], 3);
6177               field2_off += 3;
6178               found = TRUE;
6179               break;
6180             }
6181             field2_off += 3;
6182           }
6183
6184           if (!found) {
6185             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6186
6187             memcpy (outptr, empty, 3);
6188           }
6189
6190           outptr += 3;
6191         }
6192
6193         gst_buffer_unmap (outbuf, &outmap);
6194
6195         GST_BUFFER_PTS (outbuf) =
6196             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6197             GST_SECOND * CUR_STREAM (stream)->fps_d,
6198             CUR_STREAM (stream)->fps_n);
6199         GST_BUFFER_DURATION (outbuf) =
6200             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6201             CUR_STREAM (stream)->fps_n);
6202         GST_BUFFER_OFFSET (outbuf) = -1;
6203         GST_BUFFER_OFFSET_END (outbuf) = -1;
6204
6205         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6206
6207         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6208           break;
6209       }
6210       gst_buffer_unmap (buf, &map);
6211       gst_buffer_unref (buf);
6212     } else {
6213       gst_buffer_unmap (buf, &map);
6214       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6215     }
6216   } else {
6217     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6218   }
6219
6220   return ret;
6221 }
6222
6223 /* Sets a buffer's attributes properly and pushes it downstream.
6224  * Also checks for additional actions and custom processing that may
6225  * need to be done first.
6226  */
6227 static GstFlowReturn
6228 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6229     QtDemuxStream * stream, GstBuffer * buf,
6230     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6231     gboolean keyframe, GstClockTime position, guint64 byte_position)
6232 {
6233   GstFlowReturn ret = GST_FLOW_OK;
6234
6235   /* offset the timestamps according to the edit list */
6236
6237   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6238     gchar *url;
6239     GstMapInfo map;
6240
6241     gst_buffer_map (buf, &map, GST_MAP_READ);
6242     url = g_strndup ((gchar *) map.data, map.size);
6243     gst_buffer_unmap (buf, &map);
6244     if (url != NULL && strlen (url) != 0) {
6245       /* we have RTSP redirect now */
6246       g_free (qtdemux->redirect_location);
6247       qtdemux->redirect_location = g_strdup (url);
6248       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6249           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6250               gst_structure_new ("redirect",
6251                   "new-location", G_TYPE_STRING, url, NULL)));
6252     } else {
6253       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6254           "posting");
6255     }
6256     g_free (url);
6257   }
6258
6259   /* position reporting */
6260   if (qtdemux->segment.rate >= 0) {
6261     qtdemux->segment.position = position;
6262     gst_qtdemux_sync_streams (qtdemux);
6263   }
6264
6265   if (G_UNLIKELY (!stream->pad)) {
6266     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6267     gst_buffer_unref (buf);
6268     goto exit;
6269   }
6270
6271   /* send out pending buffers */
6272   while (stream->buffers) {
6273     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6274
6275     if (G_UNLIKELY (stream->discont)) {
6276       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6277       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6278       stream->discont = FALSE;
6279     } else {
6280       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6281     }
6282
6283     if (stream->alignment > 1)
6284       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6285     gst_pad_push (stream->pad, buffer);
6286
6287     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6288   }
6289
6290   /* we're going to modify the metadata */
6291   buf = gst_buffer_make_writable (buf);
6292
6293   if (qtdemux->start_utc_time != GST_CLOCK_TIME_NONE) {
6294     static GstStaticCaps unix_caps = GST_STATIC_CAPS ("timestamp/x-unix");
6295     GstCaps *caps = gst_static_caps_get (&unix_caps);
6296     gst_buffer_add_reference_timestamp_meta (buf, caps,
6297         pts + qtdemux->start_utc_time - stream->cslg_shift,
6298         GST_CLOCK_TIME_NONE);
6299     gst_caps_unref (caps);
6300   }
6301
6302   GST_BUFFER_DTS (buf) = dts;
6303   GST_BUFFER_PTS (buf) = pts;
6304   GST_BUFFER_DURATION (buf) = duration;
6305   GST_BUFFER_OFFSET (buf) = -1;
6306   GST_BUFFER_OFFSET_END (buf) = -1;
6307
6308   if (G_UNLIKELY (stream->process_func))
6309     buf = stream->process_func (qtdemux, stream, buf);
6310
6311   if (!buf) {
6312     goto exit;
6313   }
6314
6315   if (!keyframe) {
6316     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6317     stream->on_keyframe = FALSE;
6318   } else {
6319     stream->on_keyframe = TRUE;
6320   }
6321
6322   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6323     gst_buffer_append_memory (buf,
6324         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6325
6326   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6327     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6328   }
6329 #if 0
6330   if (G_UNLIKELY (qtdemux->element_index)) {
6331     GstClockTime stream_time;
6332
6333     stream_time =
6334         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6335         timestamp);
6336     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6337       GST_LOG_OBJECT (qtdemux,
6338           "adding association %" GST_TIME_FORMAT "-> %"
6339           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6340       gst_index_add_association (qtdemux->element_index,
6341           qtdemux->index_id,
6342           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6343           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6344           GST_FORMAT_BYTES, byte_position, NULL);
6345     }
6346   }
6347 #endif
6348
6349   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6350
6351 exit:
6352   return ret;
6353 }
6354
6355 static const QtDemuxRandomAccessEntry *
6356 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6357     GstClockTime pos, gboolean after)
6358 {
6359   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6360   guint n_entries = stream->n_ra_entries;
6361   guint i;
6362
6363   /* we assume the table is sorted */
6364   for (i = 0; i < n_entries; ++i) {
6365     if (entries[i].ts > pos)
6366       break;
6367   }
6368
6369   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6370    * probably okay to assume that the index lists the very first fragment */
6371   if (i == 0)
6372     return &entries[0];
6373
6374   if (after)
6375     return &entries[i];
6376   else
6377     return &entries[i - 1];
6378 }
6379
6380 static gboolean
6381 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6382 {
6383   const QtDemuxRandomAccessEntry *best_entry = NULL;
6384   gint i;
6385
6386   GST_OBJECT_LOCK (qtdemux);
6387
6388   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6389
6390   /* first see if we can determine where to go to using mfra,
6391    * before we start clearing things */
6392   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6393     const QtDemuxRandomAccessEntry *entry;
6394     QtDemuxStream *stream;
6395     gboolean is_audio_or_video;
6396
6397     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6398
6399     if (stream->ra_entries == NULL)
6400       continue;
6401
6402     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6403       is_audio_or_video = TRUE;
6404     else
6405       is_audio_or_video = FALSE;
6406
6407     entry =
6408         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6409         stream->time_position, !is_audio_or_video);
6410
6411     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6412         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6413
6414     stream->pending_seek = entry;
6415
6416     /* decide position to jump to just based on audio/video tracks, not subs */
6417     if (!is_audio_or_video)
6418       continue;
6419
6420     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6421       best_entry = entry;
6422   }
6423
6424   /* no luck, will handle seek otherwise */
6425   if (best_entry == NULL) {
6426     GST_OBJECT_UNLOCK (qtdemux);
6427     return FALSE;
6428   }
6429
6430   /* ok, now we can prepare for processing as of located moof */
6431   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6432     QtDemuxStream *stream;
6433
6434     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6435
6436     g_free (stream->samples);
6437     stream->samples = NULL;
6438     stream->n_samples = 0;
6439     stream->stbl_index = -1;    /* no samples have yet been parsed */
6440     stream->sample_index = -1;
6441
6442     if (stream->protection_scheme_info) {
6443       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6444       if (stream->protection_scheme_type == FOURCC_cenc
6445           || stream->protection_scheme_type == FOURCC_cbcs) {
6446         QtDemuxCencSampleSetInfo *info =
6447             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6448         if (info->crypto_info) {
6449           g_ptr_array_free (info->crypto_info, TRUE);
6450           info->crypto_info = NULL;
6451         }
6452       }
6453     }
6454   }
6455
6456   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6457       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6458       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6459       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6460
6461   qtdemux->moof_offset = best_entry->moof_offset;
6462
6463   qtdemux_add_fragmented_samples (qtdemux);
6464
6465   GST_OBJECT_UNLOCK (qtdemux);
6466   return TRUE;
6467 }
6468
6469 static GstFlowReturn
6470 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6471 {
6472   GstFlowReturn ret = GST_FLOW_OK;
6473   GstBuffer *buf = NULL;
6474   QtDemuxStream *stream, *target_stream = NULL;
6475   GstClockTime min_time;
6476   guint64 offset = 0;
6477   GstClockTime dts = GST_CLOCK_TIME_NONE;
6478   GstClockTime pts = GST_CLOCK_TIME_NONE;
6479   GstClockTime duration = 0;
6480   gboolean keyframe = FALSE;
6481   guint sample_size = 0;
6482   guint num_samples = 1;
6483   gboolean empty = 0;
6484   guint size;
6485   gint i;
6486
6487   if (qtdemux->fragmented_seek_pending) {
6488     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6489     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6490       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6491       qtdemux->fragmented_seek_pending = FALSE;
6492     } else {
6493       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6494     }
6495   }
6496
6497   /* Figure out the next stream sample to output, min_time is expressed in
6498    * global time and runs over the edit list segments. */
6499   min_time = G_MAXUINT64;
6500   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6501     GstClockTime position;
6502
6503     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6504     position = stream->time_position;
6505
6506     if (!GST_CLOCK_TIME_IS_VALID (position))
6507       continue;
6508
6509     if (stream->segment_index != -1) {
6510       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6511       position += segment->media_start;
6512     }
6513
6514     /* position of -1 is EOS */
6515     if (position < min_time) {
6516       min_time = position;
6517       target_stream = stream;
6518     }
6519   }
6520   /* all are EOS */
6521   if (G_UNLIKELY (target_stream == NULL)) {
6522     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6523     goto eos;
6524   }
6525
6526   /* check for segment end */
6527   if (G_UNLIKELY (qtdemux->segment.stop != -1
6528           && qtdemux->segment.rate >= 0
6529           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6530     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6531     target_stream->time_position = GST_CLOCK_TIME_NONE;
6532     goto eos_stream;
6533   }
6534
6535   /* fetch info for the current sample of this stream */
6536   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, target_stream,
6537               &empty, &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6538     goto eos_stream;
6539
6540   /* Send catche-up GAP event for each other stream if required.
6541    * This logic will be applied only for positive rate */
6542   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux) &&
6543       qtdemux->segment.rate >= 0; i++) {
6544     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6545
6546     if (stream == target_stream ||
6547         !GST_CLOCK_TIME_IS_VALID (stream->segment.stop) ||
6548         !GST_CLOCK_TIME_IS_VALID (stream->segment.position))
6549       continue;
6550
6551     if (stream->pad) {
6552       GstClockTime gap_threshold;
6553       /* kind of running time with offset segment.base and segment.start */
6554       GstClockTime pseudo_target_time = target_stream->segment.base;
6555       GstClockTime pseudo_cur_time = stream->segment.base;
6556
6557       /* make sure positive offset, segment.position can be smallr than
6558        * segment.start for some reasons */
6559       if (target_stream->segment.position >= target_stream->segment.start) {
6560         pseudo_target_time +=
6561             (target_stream->segment.position - target_stream->segment.start);
6562       }
6563
6564       if (stream->segment.position >= stream->segment.start)
6565         pseudo_cur_time += (stream->segment.position - stream->segment.start);
6566
6567       /* Only send gap events on non-subtitle streams if lagging way behind. */
6568       if (stream->subtype == FOURCC_subp
6569           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6570           stream->subtype == FOURCC_wvtt)
6571         gap_threshold = 1 * GST_SECOND;
6572       else
6573         gap_threshold = 3 * GST_SECOND;
6574
6575       /* send gap events until the stream catches up */
6576       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6577       while (GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6578           pseudo_cur_time < (G_MAXUINT64 - gap_threshold) &&
6579           pseudo_cur_time + gap_threshold < pseudo_target_time) {
6580         GstEvent *gap =
6581             gst_event_new_gap (stream->segment.position, gap_threshold);
6582         GST_LOG_OBJECT (stream->pad, "Sending %" GST_PTR_FORMAT, gap);
6583
6584         gst_pad_push_event (stream->pad, gap);
6585         stream->segment.position += gap_threshold;
6586         pseudo_cur_time += gap_threshold;
6587       }
6588     }
6589   }
6590
6591   stream = target_stream;
6592
6593   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6594   if (stream->new_caps) {
6595     gst_qtdemux_configure_stream (qtdemux, stream);
6596     qtdemux_do_allocation (stream, qtdemux);
6597   }
6598
6599   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6600   if (G_UNLIKELY (qtdemux->segment.
6601           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6602     if (stream->subtype == FOURCC_vide) {
6603       if (!keyframe) {
6604         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6605             stream->track_id);
6606         goto next;
6607       } else if (qtdemux->trickmode_interval > 0) {
6608         GstClockTimeDiff interval;
6609
6610         if (qtdemux->segment.rate > 0)
6611           interval = stream->time_position - stream->last_keyframe_dts;
6612         else
6613           interval = stream->last_keyframe_dts - stream->time_position;
6614
6615         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6616             && interval < qtdemux->trickmode_interval) {
6617           GST_LOG_OBJECT (qtdemux,
6618               "Skipping keyframe within interval on track-id %u",
6619               stream->track_id);
6620           goto next;
6621         } else {
6622           stream->last_keyframe_dts = stream->time_position;
6623         }
6624       }
6625     }
6626   }
6627
6628   GST_DEBUG_OBJECT (qtdemux,
6629       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6630       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6631       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6632       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6633       GST_TIME_ARGS (duration));
6634
6635   if (G_UNLIKELY (empty)) {
6636     /* empty segment, push a gap if there's a second or more
6637      * difference and move to the next one */
6638     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6639       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6640     stream->segment.position = pts + duration;
6641     goto next;
6642   }
6643
6644   /* hmm, empty sample, skip and move to next sample */
6645   if (G_UNLIKELY (sample_size <= 0))
6646     goto next;
6647
6648   /* last pushed sample was out of boundary, goto next sample */
6649   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6650     goto next;
6651
6652   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6653     GST_DEBUG_OBJECT (qtdemux,
6654         "size %d larger than stream max_buffer_size %d, trimming",
6655         sample_size, stream->max_buffer_size);
6656     size =
6657         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6658   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6659       && sample_size < stream->min_buffer_size) {
6660     guint start_sample_index = stream->sample_index;
6661     guint accumulated_size = sample_size;
6662     guint64 expected_next_offset = offset + sample_size;
6663
6664     GST_DEBUG_OBJECT (qtdemux,
6665         "size %d smaller than stream min_buffer_size %d, combining with the next",
6666         sample_size, stream->min_buffer_size);
6667
6668     while (stream->sample_index < stream->to_sample
6669         && stream->sample_index + 1 < stream->n_samples) {
6670       const QtDemuxSample *next_sample;
6671
6672       /* Increment temporarily */
6673       stream->sample_index++;
6674
6675       /* Failed to parse sample so let's go back to the previous one that was
6676        * still successful */
6677       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6678         stream->sample_index--;
6679         break;
6680       }
6681
6682       next_sample = &stream->samples[stream->sample_index];
6683
6684       /* Not contiguous with the previous sample so let's go back to the
6685        * previous one that was still successful */
6686       if (next_sample->offset != expected_next_offset) {
6687         stream->sample_index--;
6688         break;
6689       }
6690
6691       accumulated_size += next_sample->size;
6692       expected_next_offset += next_sample->size;
6693       if (accumulated_size >= stream->min_buffer_size)
6694         break;
6695     }
6696
6697     num_samples = stream->sample_index + 1 - start_sample_index;
6698     stream->sample_index = start_sample_index;
6699     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6700         num_samples, accumulated_size);
6701     size = accumulated_size;
6702   } else {
6703     size = sample_size;
6704   }
6705
6706   if (qtdemux->cenc_aux_info_offset > 0) {
6707     GstMapInfo map;
6708     GstByteReader br;
6709     GstBuffer *aux_info = NULL;
6710
6711     /* pull the data stored before the sample */
6712     ret =
6713         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6714         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6715     if (G_UNLIKELY (ret != GST_FLOW_OK))
6716       goto beach;
6717     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6718     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6719     gst_byte_reader_init (&br, map.data + 8, map.size);
6720     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6721             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6722       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6723       gst_buffer_unmap (aux_info, &map);
6724       gst_buffer_unref (aux_info);
6725       ret = GST_FLOW_ERROR;
6726       goto beach;
6727     }
6728     gst_buffer_unmap (aux_info, &map);
6729     gst_buffer_unref (aux_info);
6730   }
6731
6732   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6733       offset);
6734
6735   if (stream->use_allocator) {
6736     /* if we have a per-stream allocator, use it */
6737     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6738   }
6739
6740   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6741       size, &buf);
6742   if (G_UNLIKELY (ret != GST_FLOW_OK))
6743     goto beach;
6744
6745   /* Update for both splitting and combining of samples */
6746   if (size != sample_size) {
6747     pts += gst_util_uint64_scale_int (GST_SECOND,
6748         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6749         stream->timescale);
6750     dts +=
6751         gst_util_uint64_scale_int (GST_SECOND,
6752         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6753         stream->timescale);
6754     duration =
6755         gst_util_uint64_scale_int (GST_SECOND,
6756         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6757   }
6758
6759   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6760       dts, pts, duration, keyframe, min_time, offset);
6761
6762   if (size < sample_size) {
6763     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6764     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6765
6766     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6767         sample->timestamp +
6768         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6769     if (time_position >= segment->media_start) {
6770       /* inside the segment, update time_position, looks very familiar to
6771        * GStreamer segments, doesn't it? */
6772       stream->time_position = (time_position - segment->media_start) +
6773           segment->time;
6774     } else {
6775       /* not yet in segment, time does not yet increment. This means
6776        * that we are still prerolling keyframes to the decoder so it can
6777        * decode the first sample of the segment. */
6778       stream->time_position = segment->time;
6779     }
6780   } else if (size > sample_size) {
6781     /* Increase to the last sample we already pulled so that advancing
6782      * below brings us to the next sample we need to pull */
6783     stream->sample_index += num_samples - 1;
6784   }
6785
6786   /* combine flows */
6787   GST_OBJECT_LOCK (qtdemux);
6788   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6789   GST_OBJECT_UNLOCK (qtdemux);
6790   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6791    * we have no more data for the pad to push */
6792   if (ret == GST_FLOW_EOS)
6793     ret = GST_FLOW_OK;
6794
6795   stream->offset_in_sample += size;
6796   if (stream->offset_in_sample >= sample_size) {
6797     gst_qtdemux_advance_sample (qtdemux, stream);
6798   }
6799   goto beach;
6800
6801 next:
6802   gst_qtdemux_advance_sample (qtdemux, stream);
6803
6804 beach:
6805   return ret;
6806
6807   /* special cases */
6808 eos:
6809   {
6810     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6811     ret = GST_FLOW_EOS;
6812     goto beach;
6813   }
6814 eos_stream:
6815   {
6816     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6817     /* EOS will be raised if all are EOS */
6818     ret = GST_FLOW_OK;
6819     goto beach;
6820   }
6821 }
6822
6823 static void
6824 gst_qtdemux_loop (GstPad * pad)
6825 {
6826   GstQTDemux *qtdemux;
6827   guint64 cur_offset;
6828   GstFlowReturn ret;
6829
6830   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6831
6832   cur_offset = qtdemux->offset;
6833   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6834       cur_offset, qt_demux_state_string (qtdemux->state));
6835
6836   switch (qtdemux->state) {
6837     case QTDEMUX_STATE_INITIAL:
6838     case QTDEMUX_STATE_HEADER:
6839       ret = gst_qtdemux_loop_state_header (qtdemux);
6840       break;
6841     case QTDEMUX_STATE_MOVIE:
6842       ret = gst_qtdemux_loop_state_movie (qtdemux);
6843       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6844         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6845       }
6846       break;
6847     default:
6848       /* ouch */
6849       goto invalid_state;
6850   }
6851
6852   /* if something went wrong, pause */
6853   if (ret != GST_FLOW_OK)
6854     goto pause;
6855
6856 done:
6857   gst_object_unref (qtdemux);
6858   return;
6859
6860   /* ERRORS */
6861 invalid_state:
6862   {
6863     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6864         (NULL), ("streaming stopped, invalid state"));
6865     gst_pad_pause_task (pad);
6866     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6867     goto done;
6868   }
6869 pause:
6870   {
6871     const gchar *reason = gst_flow_get_name (ret);
6872
6873     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6874
6875     gst_pad_pause_task (pad);
6876
6877     /* fatal errors need special actions */
6878     /* check EOS */
6879     if (ret == GST_FLOW_EOS) {
6880       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6881         /* we have no streams, post an error */
6882         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6883       }
6884       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6885         gint64 stop;
6886
6887         if ((stop = qtdemux->segment.stop) == -1)
6888           stop = qtdemux->segment.duration;
6889
6890         if (qtdemux->segment.rate >= 0) {
6891           GstMessage *message;
6892           GstEvent *event;
6893
6894           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6895           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6896               GST_FORMAT_TIME, stop);
6897           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6898           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6899             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6900             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6901           }
6902           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6903           gst_qtdemux_push_event (qtdemux, event);
6904         } else {
6905           GstMessage *message;
6906           GstEvent *event;
6907
6908           /*  For Reverse Playback */
6909           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6910           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6911               GST_FORMAT_TIME, qtdemux->segment.start);
6912           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6913               qtdemux->segment.start);
6914           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6915             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6916             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6917           }
6918           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6919           gst_qtdemux_push_event (qtdemux, event);
6920         }
6921       } else {
6922         GstEvent *event;
6923
6924         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6925         event = gst_event_new_eos ();
6926         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6927           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6928         gst_qtdemux_push_event (qtdemux, event);
6929       }
6930     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6931       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6932       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6933     }
6934     goto done;
6935   }
6936 }
6937
6938 /*
6939  * has_next_entry
6940  *
6941  * Returns if there are samples to be played.
6942  */
6943 static gboolean
6944 has_next_entry (GstQTDemux * demux)
6945 {
6946   QtDemuxStream *stream;
6947   gint i;
6948
6949   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6950
6951   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6952     stream = QTDEMUX_NTH_STREAM (demux, i);
6953
6954     if (stream->sample_index == -1) {
6955       stream->sample_index = 0;
6956       stream->offset_in_sample = 0;
6957     }
6958
6959     if (stream->sample_index >= stream->n_samples) {
6960       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6961       continue;
6962     }
6963     GST_DEBUG_OBJECT (demux, "Found a sample");
6964     return TRUE;
6965   }
6966
6967   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6968   return FALSE;
6969 }
6970
6971 /*
6972  * next_entry_size
6973  *
6974  * Returns the size of the first entry at the current offset.
6975  * If -1, there are none (which means EOS or empty file).
6976  */
6977 static guint64
6978 next_entry_size (GstQTDemux * demux)
6979 {
6980   QtDemuxStream *stream, *target_stream = NULL;
6981   guint64 smalloffs = (guint64) - 1;
6982   QtDemuxSample *sample;
6983   gint i;
6984
6985   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6986       demux->offset);
6987
6988   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6989     stream = QTDEMUX_NTH_STREAM (demux, i);
6990
6991     if (stream->sample_index == -1) {
6992       stream->sample_index = 0;
6993       stream->offset_in_sample = 0;
6994     }
6995
6996     if (stream->sample_index >= stream->n_samples) {
6997       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6998       continue;
6999     }
7000
7001     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
7002       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
7003           stream->sample_index);
7004       return -1;
7005     }
7006
7007     sample = &stream->samples[stream->sample_index];
7008
7009     GST_LOG_OBJECT (demux,
7010         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
7011         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
7012         stream->sample_index, sample->offset, sample->size);
7013
7014     if (((smalloffs == -1)
7015             || (sample->offset < smalloffs)) && (sample->size)) {
7016       smalloffs = sample->offset;
7017       target_stream = stream;
7018     }
7019   }
7020
7021   if (!target_stream)
7022     return -1;
7023
7024   GST_LOG_OBJECT (demux,
7025       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
7026       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
7027
7028   stream = target_stream;
7029   sample = &stream->samples[stream->sample_index];
7030
7031   if (sample->offset >= demux->offset) {
7032     demux->todrop = sample->offset - demux->offset;
7033     return sample->size + demux->todrop;
7034   }
7035
7036   GST_DEBUG_OBJECT (demux,
7037       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
7038   return -1;
7039 }
7040
7041 static void
7042 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
7043 {
7044   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
7045
7046   gst_element_post_message (GST_ELEMENT_CAST (demux),
7047       gst_message_new_element (GST_OBJECT_CAST (demux),
7048           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
7049 }
7050
7051 static gboolean
7052 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
7053 {
7054   GstEvent *event;
7055   gboolean res = 0;
7056
7057   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
7058
7059   event =
7060       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
7061       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
7062       GST_SEEK_TYPE_NONE, -1);
7063
7064   /* store seqnum to drop flush events, they don't need to reach downstream */
7065   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
7066   res = gst_pad_push_event (demux->sinkpad, event);
7067   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
7068
7069   return res;
7070 }
7071
7072 /* check for seekable upstream, above and beyond a mere query */
7073 static void
7074 gst_qtdemux_check_seekability (GstQTDemux * demux)
7075 {
7076   GstQuery *query;
7077   gboolean seekable = FALSE;
7078   gint64 start = -1, stop = -1;
7079
7080   if (demux->upstream_size)
7081     return;
7082
7083   if (demux->upstream_format_is_time)
7084     return;
7085
7086   query = gst_query_new_seeking (GST_FORMAT_BYTES);
7087   if (!gst_pad_peer_query (demux->sinkpad, query)) {
7088     GST_DEBUG_OBJECT (demux, "seeking query failed");
7089     goto done;
7090   }
7091
7092   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
7093
7094   /* try harder to query upstream size if we didn't get it the first time */
7095   if (seekable && stop == -1) {
7096     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
7097     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
7098   }
7099
7100   /* if upstream doesn't know the size, it's likely that it's not seekable in
7101    * practice even if it technically may be seekable */
7102   if (seekable && (start != 0 || stop <= start)) {
7103     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
7104     seekable = FALSE;
7105   }
7106
7107 done:
7108   gst_query_unref (query);
7109
7110   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
7111       G_GUINT64_FORMAT ")", seekable, start, stop);
7112   demux->upstream_seekable = seekable;
7113   demux->upstream_size = seekable ? stop : -1;
7114 }
7115
7116 static void
7117 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
7118 {
7119   g_return_if_fail (bytes <= demux->todrop);
7120
7121   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
7122   gst_adapter_flush (demux->adapter, bytes);
7123   demux->neededbytes -= bytes;
7124   demux->offset += bytes;
7125   demux->todrop -= bytes;
7126 }
7127
7128 /* PUSH-MODE only: Send a segment, if not done already. */
7129 static void
7130 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
7131 {
7132   if (G_UNLIKELY (demux->need_segment)) {
7133     gint i;
7134
7135     if (!demux->upstream_format_is_time) {
7136       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
7137     } else {
7138       GstEvent *segment_event;
7139       segment_event = gst_event_new_segment (&demux->segment);
7140       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
7141         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
7142       gst_qtdemux_push_event (demux, segment_event);
7143     }
7144
7145     demux->need_segment = FALSE;
7146
7147     /* clear to send tags on all streams */
7148     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7149       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7150       gst_qtdemux_push_tags (demux, stream);
7151       if (CUR_STREAM (stream)->sparse) {
7152         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
7153         gst_pad_push_event (stream->pad,
7154             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
7155       }
7156     }
7157   }
7158 }
7159
7160 /* Used for push mode only. */
7161 static void
7162 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
7163     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
7164 {
7165   GstClockTime ts, dur;
7166
7167   ts = pos;
7168   dur =
7169       stream->segments[segment_index].duration - (pos -
7170       stream->segments[segment_index].time);
7171   stream->time_position += dur;
7172
7173   /* Only gaps with a duration of at least one second are propagated.
7174    * Same workaround as in pull mode.
7175    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
7176   if (dur >= GST_SECOND) {
7177     GstEvent *gap;
7178     gap = gst_event_new_gap (ts, dur);
7179
7180     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
7181         "segment: %" GST_PTR_FORMAT, gap);
7182     gst_pad_push_event (stream->pad, gap);
7183   }
7184 }
7185
7186 static GstFlowReturn
7187 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
7188 {
7189   GstQTDemux *demux;
7190
7191   demux = GST_QTDEMUX (parent);
7192
7193   GST_DEBUG_OBJECT (demux,
7194       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
7195       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
7196       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
7197       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
7198       gst_buffer_get_size (inbuf), demux->offset);
7199
7200   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
7201     gboolean is_gap_input = FALSE;
7202     gint i;
7203
7204     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
7205
7206     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7207       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
7208     }
7209
7210     /* Check if we can land back on our feet in the case where upstream is
7211      * handling the seeking/pushing of samples with gaps in between (like
7212      * in the case of trick-mode DASH for example) */
7213     if (demux->upstream_format_is_time
7214         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7215       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7216         guint32 res;
7217         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7218         GST_LOG_OBJECT (demux,
7219             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7220             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7221         res =
7222             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7223             stream, GST_BUFFER_OFFSET (inbuf));
7224         if (res != -1) {
7225           QtDemuxSample *sample = &stream->samples[res];
7226           GST_LOG_OBJECT (demux,
7227               "Checking if sample %d from track-id %u is valid (offset:%"
7228               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7229               stream->track_id, sample->offset, sample->size);
7230           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7231             GST_LOG_OBJECT (demux,
7232                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7233                 res);
7234             is_gap_input = TRUE;
7235             /* We can go back to standard playback mode */
7236             demux->state = QTDEMUX_STATE_MOVIE;
7237             /* Remember which sample this stream is at */
7238             stream->sample_index = res;
7239             /* Finally update all push-based values to the expected values */
7240             demux->neededbytes = stream->samples[res].size;
7241             demux->offset = GST_BUFFER_OFFSET (inbuf);
7242             demux->mdatleft =
7243                 demux->mdatsize - demux->offset + demux->mdatoffset;
7244             demux->todrop = 0;
7245           }
7246         }
7247       }
7248       if (!is_gap_input) {
7249         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7250         /* Reset state if it's a real discont */
7251         demux->neededbytes = 16;
7252         demux->state = QTDEMUX_STATE_INITIAL;
7253         demux->offset = GST_BUFFER_OFFSET (inbuf);
7254         gst_adapter_clear (demux->adapter);
7255       }
7256     }
7257     /* Reverse fragmented playback, need to flush all we have before
7258      * consuming a new fragment.
7259      * The samples array have the timestamps calculated by accumulating the
7260      * durations but this won't work for reverse playback of fragments as
7261      * the timestamps of a subsequent fragment should be smaller than the
7262      * previously received one. */
7263     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7264       gst_qtdemux_process_adapter (demux, TRUE);
7265       g_ptr_array_foreach (demux->active_streams,
7266           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7267     }
7268   }
7269
7270   gst_adapter_push (demux->adapter, inbuf);
7271
7272   GST_DEBUG_OBJECT (demux,
7273       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7274       demux->neededbytes, gst_adapter_available (demux->adapter));
7275
7276   return gst_qtdemux_process_adapter (demux, FALSE);
7277 }
7278
7279 static GstFlowReturn
7280 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7281 {
7282   GstFlowReturn ret = GST_FLOW_OK;
7283
7284   /* we never really mean to buffer that much */
7285   if (demux->neededbytes == -1) {
7286     goto eos;
7287   }
7288
7289   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7290       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7291
7292 #ifndef GST_DISABLE_GST_DEBUG
7293     {
7294       guint64 discont_offset, distance_from_discont;
7295
7296       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7297       distance_from_discont =
7298           gst_adapter_distance_from_discont (demux->adapter);
7299
7300       GST_DEBUG_OBJECT (demux,
7301           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7302           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7303           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7304           demux->offset, discont_offset, distance_from_discont);
7305     }
7306 #endif
7307
7308     switch (demux->state) {
7309       case QTDEMUX_STATE_INITIAL:{
7310         const guint8 *data;
7311         guint32 fourcc;
7312         guint64 size;
7313
7314         gst_qtdemux_check_seekability (demux);
7315
7316         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7317
7318         /* get fourcc/length, set neededbytes */
7319         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7320             &size, &fourcc);
7321         gst_adapter_unmap (demux->adapter);
7322         data = NULL;
7323         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7324             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7325         if (size == 0) {
7326           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7327               (_("This file is invalid and cannot be played.")),
7328               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7329                   GST_FOURCC_ARGS (fourcc)));
7330           ret = GST_FLOW_ERROR;
7331           break;
7332         }
7333         if (fourcc == FOURCC_mdat) {
7334           gint next_entry = next_entry_size (demux);
7335           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7336                   || !demux->fragmented)) {
7337             /* we have the headers, start playback */
7338             demux->state = QTDEMUX_STATE_MOVIE;
7339             demux->neededbytes = next_entry;
7340             demux->mdatleft = size;
7341             demux->mdatsize = demux->mdatleft;
7342           } else {
7343             /* no headers yet, try to get them */
7344             guint bs;
7345             gboolean res;
7346             guint64 old, target;
7347
7348           buffer_data:
7349             old = demux->offset;
7350             target = old + size;
7351
7352             /* try to jump over the atom with a seek */
7353             /* only bother if it seems worth doing so,
7354              * and avoids possible upstream/server problems */
7355             if (demux->upstream_seekable &&
7356                 demux->upstream_size > 4 * (1 << 20)) {
7357               res = qtdemux_seek_offset (demux, target);
7358             } else {
7359               GST_DEBUG_OBJECT (demux, "skipping seek");
7360               res = FALSE;
7361             }
7362
7363             if (res) {
7364               GST_DEBUG_OBJECT (demux, "seek success");
7365               /* remember the offset fo the first mdat so we can seek back to it
7366                * after we have the headers */
7367               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7368                 demux->first_mdat = old;
7369                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7370                     demux->first_mdat);
7371               }
7372               /* seek worked, continue reading */
7373               demux->offset = target;
7374               demux->neededbytes = 16;
7375               demux->state = QTDEMUX_STATE_INITIAL;
7376             } else {
7377               /* seek failed, need to buffer */
7378               demux->offset = old;
7379               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7380               /* there may be multiple mdat (or alike) buffers */
7381               /* sanity check */
7382               if (demux->mdatbuffer)
7383                 bs = gst_buffer_get_size (demux->mdatbuffer);
7384               else
7385                 bs = 0;
7386               if (size + bs > 10 * (1 << 20))
7387                 goto no_moov;
7388               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7389               demux->neededbytes = size;
7390               if (!demux->mdatbuffer)
7391                 demux->mdatoffset = demux->offset;
7392             }
7393           }
7394         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7395           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7396               (_("This file is invalid and cannot be played.")),
7397               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7398                   GST_FOURCC_ARGS (fourcc), size));
7399           ret = GST_FLOW_ERROR;
7400           break;
7401         } else {
7402           /* this means we already started buffering and still no moov header,
7403            * let's continue buffering everything till we get moov */
7404           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7405                   || fourcc == FOURCC_moof))
7406             goto buffer_data;
7407           demux->neededbytes = size;
7408           demux->state = QTDEMUX_STATE_HEADER;
7409         }
7410         break;
7411       }
7412       case QTDEMUX_STATE_HEADER:{
7413         const guint8 *data;
7414         guint32 fourcc;
7415
7416         GST_DEBUG_OBJECT (demux, "In header");
7417
7418         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7419
7420         /* parse the header */
7421         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7422             &fourcc);
7423         if (fourcc == FOURCC_moov) {
7424           /* in usual fragmented setup we could try to scan for more
7425            * and end up at the the moov (after mdat) again */
7426           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7427               (!demux->fragmented
7428                   || demux->last_moov_offset == demux->offset)) {
7429             GST_DEBUG_OBJECT (demux,
7430                 "Skipping moov atom as we have (this) one already");
7431           } else {
7432             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7433
7434             if (demux->got_moov && demux->fragmented) {
7435               GST_DEBUG_OBJECT (demux,
7436                   "Got a second moov, clean up data from old one");
7437               if (demux->moov_node_compressed) {
7438                 g_node_destroy (demux->moov_node_compressed);
7439                 if (demux->moov_node)
7440                   g_free (demux->moov_node->data);
7441               }
7442               demux->moov_node_compressed = NULL;
7443               if (demux->moov_node)
7444                 g_node_destroy (demux->moov_node);
7445               demux->moov_node = NULL;
7446               demux->start_utc_time = GST_CLOCK_TIME_NONE;
7447             }
7448
7449             demux->last_moov_offset = demux->offset;
7450
7451             /* Update streams with new moov */
7452             gst_qtdemux_stream_concat (demux,
7453                 demux->old_streams, demux->active_streams);
7454
7455             qtdemux_parse_moov (demux, data, demux->neededbytes);
7456             qtdemux_node_dump (demux, demux->moov_node);
7457             qtdemux_parse_tree (demux);
7458             qtdemux_prepare_streams (demux);
7459             QTDEMUX_EXPOSE_LOCK (demux);
7460             qtdemux_expose_streams (demux);
7461             QTDEMUX_EXPOSE_UNLOCK (demux);
7462
7463             demux->got_moov = TRUE;
7464
7465             gst_qtdemux_check_send_pending_segment (demux);
7466
7467             if (demux->moov_node_compressed) {
7468               g_node_destroy (demux->moov_node_compressed);
7469               g_free (demux->moov_node->data);
7470             }
7471             demux->moov_node_compressed = NULL;
7472             g_node_destroy (demux->moov_node);
7473             demux->moov_node = NULL;
7474             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7475           }
7476         } else if (fourcc == FOURCC_moof) {
7477           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7478             guint64 dist = 0;
7479             GstClockTime prev_pts;
7480             guint64 prev_offset;
7481             guint64 adapter_discont_offset, adapter_discont_dist;
7482
7483             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7484
7485             /*
7486              * The timestamp of the moof buffer is relevant as some scenarios
7487              * won't have the initial timestamp in the atoms. Whenever a new
7488              * buffer has started, we get that buffer's PTS and use it as a base
7489              * timestamp for the trun entries.
7490              *
7491              * To keep track of the current buffer timestamp and starting point
7492              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7493              * from the beginning of the buffer, with the distance and demux->offset
7494              * we know if it is still the same buffer or not.
7495              */
7496             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7497             prev_offset = demux->offset - dist;
7498             if (demux->fragment_start_offset == -1
7499                 || prev_offset > demux->fragment_start_offset) {
7500               demux->fragment_start_offset = prev_offset;
7501               demux->fragment_start = prev_pts;
7502               GST_DEBUG_OBJECT (demux,
7503                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7504                   GST_TIME_FORMAT, demux->fragment_start_offset,
7505                   GST_TIME_ARGS (demux->fragment_start));
7506             }
7507
7508             /* We can't use prev_offset() here because this would require
7509              * upstream to set consistent and correct offsets on all buffers
7510              * since the discont. Nothing ever did that in the past and we
7511              * would break backwards compatibility here then.
7512              * Instead take the offset we had at the last discont and count
7513              * the bytes from there. This works with old code as there would
7514              * be no discont between moov and moof, and also works with
7515              * adaptivedemux which correctly sets offset and will set the
7516              * DISCONT flag accordingly when needed.
7517              *
7518              * We also only do this for upstream TIME segments as otherwise
7519              * there are potential backwards compatibility problems with
7520              * seeking in PUSH mode and upstream providing inconsistent
7521              * timestamps. */
7522             adapter_discont_offset =
7523                 gst_adapter_offset_at_discont (demux->adapter);
7524             adapter_discont_dist =
7525                 gst_adapter_distance_from_discont (demux->adapter);
7526
7527             GST_DEBUG_OBJECT (demux,
7528                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7529                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7530                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7531
7532             if (demux->upstream_format_is_time) {
7533               demux->moof_offset = adapter_discont_offset;
7534               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7535                 demux->moof_offset += adapter_discont_dist;
7536               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7537                 demux->moof_offset = demux->offset;
7538             } else {
7539               demux->moof_offset = demux->offset;
7540             }
7541
7542             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7543                     demux->moof_offset, NULL)) {
7544               gst_adapter_unmap (demux->adapter);
7545               ret = GST_FLOW_ERROR;
7546               goto done;
7547             }
7548
7549             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7550             if (demux->mss_mode && !demux->exposed) {
7551               QTDEMUX_EXPOSE_LOCK (demux);
7552               qtdemux_expose_streams (demux);
7553               QTDEMUX_EXPOSE_UNLOCK (demux);
7554             }
7555
7556             gst_qtdemux_check_send_pending_segment (demux);
7557           } else {
7558             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7559           }
7560         } else if (fourcc == FOURCC_ftyp) {
7561           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7562           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7563         } else if (fourcc == FOURCC_uuid) {
7564           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7565           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7566         } else if (fourcc == FOURCC_sidx) {
7567           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7568           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7569         } else if (fourcc == FOURCC_meta) {
7570           GNode *node, *child;
7571           GstByteReader child_data;
7572
7573           node = g_node_new ((gpointer) data);
7574           qtdemux_parse_node (demux, node, data, demux->neededbytes);
7575
7576           /* Parse ONVIF Export File Format CorrectStartTime box if available */
7577           if ((child =
7578                   qtdemux_tree_get_child_by_type_full (node, FOURCC_cstb,
7579                       &child_data))) {
7580             qtdemux_parse_cstb (demux, &child_data);
7581           }
7582
7583           g_node_destroy (node);
7584         } else {
7585           switch (fourcc) {
7586             case FOURCC_styp:
7587               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7588                * FALLTHROUGH */
7589             case FOURCC_skip:
7590             case FOURCC_free:
7591               /* [free] and [skip] are padding atoms */
7592               GST_DEBUG_OBJECT (demux,
7593                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7594                   GST_FOURCC_ARGS (fourcc));
7595               break;
7596             default:
7597               GST_WARNING_OBJECT (demux,
7598                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7599                   GST_FOURCC_ARGS (fourcc));
7600               /* Let's jump that one and go back to initial state */
7601               break;
7602           }
7603         }
7604         gst_adapter_unmap (demux->adapter);
7605         data = NULL;
7606
7607         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7608           gsize remaining_data_size = 0;
7609
7610           /* the mdat was before the header */
7611           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7612               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7613           /* restore our adapter/offset view of things with upstream;
7614            * put preceding buffered data ahead of current moov data.
7615            * This should also handle evil mdat, moov, mdat cases and alike */
7616           gst_adapter_flush (demux->adapter, demux->neededbytes);
7617
7618           /* Store any remaining data after the mdat for later usage */
7619           remaining_data_size = gst_adapter_available (demux->adapter);
7620           if (remaining_data_size > 0) {
7621             g_assert (demux->restoredata_buffer == NULL);
7622             demux->restoredata_buffer =
7623                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7624             demux->restoredata_offset = demux->offset + demux->neededbytes;
7625             GST_DEBUG_OBJECT (demux,
7626                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7627                 G_GUINT64_FORMAT, remaining_data_size,
7628                 demux->restoredata_offset);
7629           }
7630
7631           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7632           demux->mdatbuffer = NULL;
7633           demux->offset = demux->mdatoffset;
7634           demux->neededbytes = next_entry_size (demux);
7635           demux->state = QTDEMUX_STATE_MOVIE;
7636           demux->mdatleft = gst_adapter_available (demux->adapter);
7637           demux->mdatsize = demux->mdatleft;
7638         } else {
7639           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7640           gst_adapter_flush (demux->adapter, demux->neededbytes);
7641
7642           /* only go back to the mdat if there are samples to play */
7643           if (demux->got_moov && demux->first_mdat != -1
7644               && has_next_entry (demux)) {
7645             gboolean res;
7646
7647             /* we need to seek back */
7648             res = qtdemux_seek_offset (demux, demux->first_mdat);
7649             if (res) {
7650               demux->offset = demux->first_mdat;
7651             } else {
7652               GST_DEBUG_OBJECT (demux, "Seek back failed");
7653             }
7654           } else {
7655             demux->offset += demux->neededbytes;
7656           }
7657           demux->neededbytes = 16;
7658           demux->state = QTDEMUX_STATE_INITIAL;
7659         }
7660
7661         break;
7662       }
7663       case QTDEMUX_STATE_BUFFER_MDAT:{
7664         GstBuffer *buf;
7665         guint8 fourcc[4];
7666
7667         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7668             demux->offset);
7669         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7670         gst_buffer_extract (buf, 0, fourcc, 4);
7671         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7672             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7673         if (demux->mdatbuffer)
7674           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7675         else
7676           demux->mdatbuffer = buf;
7677         demux->offset += demux->neededbytes;
7678         demux->neededbytes = 16;
7679         demux->state = QTDEMUX_STATE_INITIAL;
7680         gst_qtdemux_post_progress (demux, 1, 1);
7681
7682         break;
7683       }
7684       case QTDEMUX_STATE_MOVIE:{
7685         QtDemuxStream *stream = NULL;
7686         QtDemuxSample *sample;
7687         GstClockTime dts, pts, duration;
7688         gboolean keyframe;
7689         gint i;
7690
7691         GST_DEBUG_OBJECT (demux,
7692             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7693
7694         if (demux->fragmented) {
7695           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7696               demux->mdatleft);
7697           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7698             /* if needed data starts within this atom,
7699              * then it should not exceed this atom */
7700             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7701               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7702                   (_("This file is invalid and cannot be played.")),
7703                   ("sample data crosses atom boundary"));
7704               ret = GST_FLOW_ERROR;
7705               break;
7706             }
7707             demux->mdatleft -= demux->neededbytes;
7708           } else {
7709             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7710             /* so we are dropping more than left in this atom */
7711             gst_qtdemux_drop_data (demux, demux->mdatleft);
7712             demux->mdatleft = 0;
7713
7714             /* need to resume atom parsing so we do not miss any other pieces */
7715             demux->state = QTDEMUX_STATE_INITIAL;
7716             demux->neededbytes = 16;
7717
7718             /* check if there was any stored post mdat data from previous buffers */
7719             if (demux->restoredata_buffer) {
7720               g_assert (gst_adapter_available (demux->adapter) == 0);
7721
7722               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7723               demux->restoredata_buffer = NULL;
7724               demux->offset = demux->restoredata_offset;
7725             }
7726
7727             break;
7728           }
7729         }
7730
7731         if (demux->todrop) {
7732           if (demux->cenc_aux_info_offset > 0) {
7733             GstByteReader br;
7734             const guint8 *data;
7735
7736             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7737             data = gst_adapter_map (demux->adapter, demux->todrop);
7738             gst_byte_reader_init (&br, data + 8, demux->todrop);
7739             if (!qtdemux_parse_cenc_aux_info (demux,
7740                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7741                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7742               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7743               ret = GST_FLOW_ERROR;
7744               gst_adapter_unmap (demux->adapter);
7745               g_free (demux->cenc_aux_info_sizes);
7746               demux->cenc_aux_info_sizes = NULL;
7747               goto done;
7748             }
7749             demux->cenc_aux_info_offset = 0;
7750             g_free (demux->cenc_aux_info_sizes);
7751             demux->cenc_aux_info_sizes = NULL;
7752             gst_adapter_unmap (demux->adapter);
7753           }
7754           gst_qtdemux_drop_data (demux, demux->todrop);
7755         }
7756
7757         /* first buffer? */
7758         /* initial newsegment sent here after having added pads,
7759          * possible others in sink_event */
7760         gst_qtdemux_check_send_pending_segment (demux);
7761
7762         /* Figure out which stream this packet belongs to */
7763         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7764           stream = QTDEMUX_NTH_STREAM (demux, i);
7765           if (stream->sample_index >= stream->n_samples) {
7766             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7767             stream = NULL;
7768             continue;
7769           }
7770           GST_LOG_OBJECT (demux,
7771               "Checking track-id %u (sample_index:%d / offset:%"
7772               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7773               stream->sample_index,
7774               stream->samples[stream->sample_index].offset,
7775               stream->samples[stream->sample_index].size);
7776
7777           if (stream->samples[stream->sample_index].offset == demux->offset)
7778             break;
7779         }
7780
7781         if (G_UNLIKELY (stream == NULL))
7782           goto unknown_stream;
7783
7784         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7785
7786         if (stream->new_caps) {
7787           gst_qtdemux_configure_stream (demux, stream);
7788         }
7789
7790         /* Put data in a buffer, set timestamps, caps, ... */
7791         sample = &stream->samples[stream->sample_index];
7792
7793         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7794           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7795               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7796
7797           dts = QTSAMPLE_DTS (stream, sample);
7798           pts = QTSAMPLE_PTS (stream, sample);
7799           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7800           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7801
7802           /* check for segment end */
7803           if (G_UNLIKELY (demux->segment.stop != -1
7804                   && demux->segment.stop <= pts && stream->on_keyframe)
7805               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7806             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7807             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7808
7809             /* skip this data, stream is EOS */
7810             gst_adapter_flush (demux->adapter, demux->neededbytes);
7811             demux->offset += demux->neededbytes;
7812
7813             /* check if all streams are eos */
7814             ret = GST_FLOW_EOS;
7815             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7816               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7817                 ret = GST_FLOW_OK;
7818                 break;
7819               }
7820             }
7821           } else {
7822             GstBuffer *outbuf;
7823
7824             outbuf =
7825                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7826
7827             /* FIXME: should either be an assert or a plain check */
7828             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7829
7830             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7831                 dts, pts, duration, keyframe, dts, demux->offset);
7832           }
7833
7834           /* combine flows */
7835           GST_OBJECT_LOCK (demux);
7836           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7837           GST_OBJECT_UNLOCK (demux);
7838         } else {
7839           /* skip this data, stream is EOS */
7840           gst_adapter_flush (demux->adapter, demux->neededbytes);
7841         }
7842
7843         stream->sample_index++;
7844         stream->offset_in_sample = 0;
7845
7846         /* update current offset and figure out size of next buffer */
7847         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7848             demux->offset, demux->neededbytes);
7849         demux->offset += demux->neededbytes;
7850         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7851             demux->offset);
7852
7853
7854         if (ret == GST_FLOW_EOS) {
7855           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7856           demux->neededbytes = -1;
7857           goto eos;
7858         }
7859
7860         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7861           if (demux->fragmented) {
7862             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7863             /* there may be more to follow, only finish this atom */
7864             demux->todrop = demux->mdatleft;
7865             demux->neededbytes = demux->todrop;
7866             break;
7867           }
7868           goto eos;
7869         }
7870         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7871           goto non_ok_unlinked_flow;
7872         }
7873         break;
7874       }
7875       default:
7876         goto invalid_state;
7877     }
7878   }
7879
7880   /* when buffering movie data, at least show user something is happening */
7881   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7882       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7883     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7884         demux->neededbytes);
7885   }
7886 done:
7887
7888   return ret;
7889
7890   /* ERRORS */
7891 non_ok_unlinked_flow:
7892   {
7893     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7894         gst_flow_get_name (ret));
7895     return ret;
7896   }
7897 unknown_stream:
7898   {
7899     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7900     ret = GST_FLOW_ERROR;
7901     goto done;
7902   }
7903 eos:
7904   {
7905     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7906     ret = GST_FLOW_EOS;
7907     goto done;
7908   }
7909 invalid_state:
7910   {
7911     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7912         (NULL), ("qtdemuxer invalid state %d", demux->state));
7913     ret = GST_FLOW_ERROR;
7914     goto done;
7915   }
7916 no_moov:
7917   {
7918     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7919         (NULL), ("no 'moov' atom within the first 10 MB"));
7920     ret = GST_FLOW_ERROR;
7921     goto done;
7922   }
7923 }
7924
7925 static gboolean
7926 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7927 {
7928   GstQuery *query;
7929   gboolean pull_mode;
7930
7931   query = gst_query_new_scheduling ();
7932
7933   if (!gst_pad_peer_query (sinkpad, query)) {
7934     gst_query_unref (query);
7935     goto activate_push;
7936   }
7937
7938   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7939       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7940   gst_query_unref (query);
7941
7942   if (!pull_mode)
7943     goto activate_push;
7944
7945   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7946   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7947
7948 activate_push:
7949   {
7950     GST_DEBUG_OBJECT (sinkpad, "activating push");
7951     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7952   }
7953 }
7954
7955 static gboolean
7956 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7957     GstPadMode mode, gboolean active)
7958 {
7959   gboolean res;
7960   GstQTDemux *demux = GST_QTDEMUX (parent);
7961
7962   switch (mode) {
7963     case GST_PAD_MODE_PUSH:
7964       demux->pullbased = FALSE;
7965       res = TRUE;
7966       break;
7967     case GST_PAD_MODE_PULL:
7968       if (active) {
7969         demux->pullbased = TRUE;
7970         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7971             sinkpad, NULL);
7972       } else {
7973         res = gst_pad_stop_task (sinkpad);
7974       }
7975       break;
7976     default:
7977       res = FALSE;
7978       break;
7979   }
7980   return res;
7981 }
7982
7983 #ifdef HAVE_ZLIB
7984 static void *
7985 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7986 {
7987   guint8 *buffer;
7988   z_stream z;
7989   int ret;
7990
7991   memset (&z, 0, sizeof (z));
7992   z.zalloc = NULL;
7993   z.zfree = NULL;
7994   z.opaque = NULL;
7995
7996   if ((ret = inflateInit (&z)) != Z_OK) {
7997     GST_ERROR ("inflateInit() returned %d", ret);
7998     return NULL;
7999   }
8000
8001   z.next_in = z_buffer;
8002   z.avail_in = z_length;
8003
8004   buffer = (guint8 *) g_malloc (*length);
8005   z.avail_out = *length;
8006   z.next_out = (Bytef *) buffer;
8007   do {
8008     ret = inflate (&z, Z_NO_FLUSH);
8009     if (ret == Z_STREAM_END) {
8010       break;
8011     } else if (ret != Z_OK) {
8012       GST_WARNING ("inflate() returned %d", ret);
8013       break;
8014     }
8015
8016     if (*length > G_MAXUINT - 4096 || *length > QTDEMUX_MAX_SAMPLE_INDEX_SIZE) {
8017       GST_WARNING ("too big decompressed data");
8018       ret = Z_MEM_ERROR;
8019       break;
8020     }
8021
8022     *length += 4096;
8023     buffer = (guint8 *) g_realloc (buffer, *length);
8024     z.next_out = (Bytef *) (buffer + z.total_out);
8025     z.avail_out += *length - z.total_out;
8026   } while (z.avail_in > 0);
8027
8028   if (ret != Z_STREAM_END) {
8029     g_free (buffer);
8030     buffer = NULL;
8031     *length = 0;
8032   } else {
8033     *length = z.total_out;
8034   }
8035
8036   inflateEnd (&z);
8037
8038   return buffer;
8039 }
8040 #endif /* HAVE_ZLIB */
8041
8042 static gboolean
8043 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
8044 {
8045   GNode *cmov;
8046
8047   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
8048
8049   /* counts as header data */
8050   qtdemux->header_size += length;
8051
8052   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
8053   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
8054
8055   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
8056   if (cmov) {
8057     guint32 method;
8058     GNode *dcom;
8059     GNode *cmvd;
8060     guint32 dcom_len;
8061
8062     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
8063     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
8064     if (dcom == NULL || cmvd == NULL)
8065       goto invalid_compression;
8066
8067     dcom_len = QT_UINT32 (dcom->data);
8068     if (dcom_len < 12)
8069       goto invalid_compression;
8070
8071     method = QT_FOURCC ((guint8 *) dcom->data + 8);
8072     switch (method) {
8073 #ifdef HAVE_ZLIB
8074       case FOURCC_zlib:{
8075         guint uncompressed_length;
8076         guint compressed_length;
8077         guint8 *buf;
8078         guint32 cmvd_len;
8079
8080         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
8081         if (cmvd_len < 12)
8082           goto invalid_compression;
8083
8084         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
8085         compressed_length = cmvd_len - 12;
8086         GST_LOG ("length = %u", uncompressed_length);
8087
8088         buf =
8089             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
8090             compressed_length, &uncompressed_length);
8091
8092         if (buf) {
8093           qtdemux->moov_node_compressed = qtdemux->moov_node;
8094           qtdemux->moov_node = g_node_new (buf);
8095
8096           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
8097               uncompressed_length);
8098         }
8099         break;
8100       }
8101 #endif /* HAVE_ZLIB */
8102       default:
8103         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
8104             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
8105         break;
8106     }
8107   }
8108   return TRUE;
8109
8110   /* ERRORS */
8111 invalid_compression:
8112   {
8113     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
8114     return FALSE;
8115   }
8116 }
8117
8118 static gboolean
8119 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
8120     const guint8 * end)
8121 {
8122   while (G_UNLIKELY (buf < end)) {
8123     GNode *child;
8124     guint32 len;
8125
8126     if (G_UNLIKELY (buf + 4 > end)) {
8127       GST_LOG_OBJECT (qtdemux, "buffer overrun");
8128       break;
8129     }
8130     len = QT_UINT32 (buf);
8131     if (G_UNLIKELY (len == 0)) {
8132       GST_LOG_OBJECT (qtdemux, "empty container");
8133       break;
8134     }
8135     if (G_UNLIKELY (len < 8)) {
8136       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
8137       break;
8138     }
8139     if (G_UNLIKELY (len > (end - buf))) {
8140       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
8141           (gint) (end - buf));
8142       break;
8143     }
8144
8145     child = g_node_new ((guint8 *) buf);
8146     g_node_append (node, child);
8147     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
8148     qtdemux_parse_node (qtdemux, child, buf, len);
8149
8150     buf += len;
8151   }
8152   return TRUE;
8153 }
8154
8155 static gboolean
8156 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
8157     GNode * xdxt)
8158 {
8159   int len = QT_UINT32 (xdxt->data);
8160   guint8 *buf = xdxt->data;
8161   guint8 *end = buf + len;
8162   GstBuffer *buffer;
8163
8164   /* skip size and type */
8165   buf += 8;
8166   end -= 8;
8167
8168   while (buf < end) {
8169     gint size;
8170     guint32 type;
8171
8172     size = QT_UINT32 (buf);
8173     type = QT_FOURCC (buf + 4);
8174
8175     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
8176
8177     if (buf + size > end || size <= 0)
8178       break;
8179
8180     buf += 8;
8181     size -= 8;
8182
8183     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
8184         GST_FOURCC_ARGS (type));
8185
8186     switch (type) {
8187       case FOURCC_tCtH:
8188         buffer = gst_buffer_new_and_alloc (size);
8189         gst_buffer_fill (buffer, 0, buf, size);
8190         stream->buffers = g_slist_append (stream->buffers, buffer);
8191         GST_LOG_OBJECT (qtdemux, "parsing theora header");
8192         break;
8193       case FOURCC_tCt_:
8194         buffer = gst_buffer_new_and_alloc (size);
8195         gst_buffer_fill (buffer, 0, buf, size);
8196         stream->buffers = g_slist_append (stream->buffers, buffer);
8197         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
8198         break;
8199       case FOURCC_tCtC:
8200         buffer = gst_buffer_new_and_alloc (size);
8201         gst_buffer_fill (buffer, 0, buf, size);
8202         stream->buffers = g_slist_append (stream->buffers, buffer);
8203         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
8204         break;
8205       default:
8206         GST_WARNING_OBJECT (qtdemux,
8207             "unknown theora cookie %" GST_FOURCC_FORMAT,
8208             GST_FOURCC_ARGS (type));
8209         break;
8210     }
8211     buf += size;
8212   }
8213   return TRUE;
8214 }
8215
8216 static gboolean
8217 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
8218     guint length)
8219 {
8220   guint32 fourcc = 0;
8221   guint32 node_length = 0;
8222   const QtNodeType *type;
8223   const guint8 *end;
8224
8225   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
8226
8227   if (G_UNLIKELY (length < 8))
8228     goto not_enough_data;
8229
8230   node_length = QT_UINT32 (buffer);
8231   fourcc = QT_FOURCC (buffer + 4);
8232
8233   /* ignore empty nodes */
8234   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
8235     return TRUE;
8236
8237   type = qtdemux_type_get (fourcc);
8238
8239   end = buffer + length;
8240
8241   GST_LOG_OBJECT (qtdemux,
8242       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8243       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8244
8245   if (node_length > length)
8246     goto broken_atom_size;
8247
8248   if (type->flags & QT_FLAG_CONTAINER) {
8249     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8250   } else {
8251     switch (fourcc) {
8252       case FOURCC_stsd:
8253       {
8254         if (node_length < 20) {
8255           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8256           break;
8257         }
8258         GST_DEBUG_OBJECT (qtdemux,
8259             "parsing stsd (sample table, sample description) atom");
8260         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8261         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8262         break;
8263       }
8264       case FOURCC_mp4a:
8265       case FOURCC_alac:
8266       case FOURCC_fLaC:
8267       case FOURCC_aavd:
8268       {
8269         guint32 version;
8270         guint32 offset;
8271         guint min_size;
8272
8273         /* also read alac (or whatever) in stead of mp4a in the following,
8274          * since a similar layout is used in other cases as well */
8275         if (fourcc == FOURCC_mp4a)
8276           min_size = 20;
8277         else if (fourcc == FOURCC_fLaC)
8278           min_size = 86;
8279         else
8280           min_size = 40;
8281
8282         /* There are two things we might encounter here: a true mp4a atom, and
8283            an mp4a entry in an stsd atom. The latter is what we're interested
8284            in, and it looks like an atom, but isn't really one. The true mp4a
8285            atom is short, so we detect it based on length here. */
8286         if (length < min_size) {
8287           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8288               GST_FOURCC_ARGS (fourcc));
8289           break;
8290         }
8291
8292         /* 'version' here is the sound sample description version. Types 0 and
8293            1 are documented in the QTFF reference, but type 2 is not: it's
8294            described in Apple header files instead (struct SoundDescriptionV2
8295            in Movies.h) */
8296         version = QT_UINT16 (buffer + 16);
8297
8298         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8299             GST_FOURCC_ARGS (fourcc), version);
8300
8301         /* parse any esds descriptors */
8302         switch (version) {
8303           case 0:
8304             offset = 0x24;
8305             break;
8306           case 1:
8307             offset = 0x34;
8308             break;
8309           case 2:
8310             offset = 0x48;
8311             break;
8312           default:
8313             GST_WARNING_OBJECT (qtdemux,
8314                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8315                 GST_FOURCC_ARGS (fourcc), version);
8316             offset = 0;
8317             break;
8318         }
8319         if (offset)
8320           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8321         break;
8322       }
8323       case FOURCC_mp4v:
8324       case FOURCC_MP4V:
8325       case FOURCC_fmp4:
8326       case FOURCC_FMP4:
8327       case FOURCC_apcs:
8328       case FOURCC_apch:
8329       case FOURCC_apcn:
8330       case FOURCC_apco:
8331       case FOURCC_ap4h:
8332       case FOURCC_xvid:
8333       case FOURCC_XVID:
8334       case FOURCC_H264:
8335       case FOURCC_avc1:
8336       case FOURCC_avc3:
8337       case FOURCC_H265:
8338       case FOURCC_hvc1:
8339       case FOURCC_hev1:
8340       case FOURCC_dvh1:
8341       case FOURCC_dvhe:
8342       case FOURCC_mjp2:
8343       case FOURCC_encv:
8344       {
8345         guint32 version;
8346         guint32 str_len;
8347
8348         /* codec_data is contained inside these atoms, which all have
8349          * the same format. */
8350         /* video sample description size is 86 bytes without extension.
8351          * node_length have to be bigger than 86 bytes because video sample
8352          * description can include extensions such as esds, fiel, glbl, etc. */
8353         if (node_length < 86) {
8354           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8355               " sample description length too short (%u < 86)",
8356               GST_FOURCC_ARGS (fourcc), node_length);
8357           break;
8358         }
8359
8360         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8361             GST_FOURCC_ARGS (fourcc));
8362
8363         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8364          *              its data format.
8365          * revision level (2 bytes) : must be set to 0. */
8366         version = QT_UINT32 (buffer + 16);
8367         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8368
8369         /* compressor name : PASCAL string and informative purposes
8370          * first byte : the number of bytes to be displayed.
8371          *              it has to be less than 32 because it is reserved
8372          *              space of 32 bytes total including itself. */
8373         str_len = QT_UINT8 (buffer + 50);
8374         if (str_len < 32)
8375           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8376               (char *) buffer + 51);
8377         else
8378           GST_WARNING_OBJECT (qtdemux,
8379               "compressorname length too big (%u > 31)", str_len);
8380
8381         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8382             end - buffer);
8383         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8384         break;
8385       }
8386       case FOURCC_meta:
8387       {
8388         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8389
8390         /* You are reading this correctly. QTFF specifies that the
8391          * metadata atom is a short atom, whereas ISO BMFF specifies
8392          * it's a full atom. But since so many people are doing things
8393          * differently, we actually peek into the atom to see which
8394          * variant it is */
8395         if (length < 16) {
8396           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8397               GST_FOURCC_ARGS (fourcc));
8398           break;
8399         }
8400         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8401           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8402            * starts with a 'hdlr' atom */
8403           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8404         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8405           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8406            * with version/flags both set to zero */
8407           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8408         } else
8409           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8410         break;
8411       }
8412       case FOURCC_mp4s:
8413       {
8414         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8415         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8416         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8417         break;
8418       }
8419       case FOURCC_XiTh:
8420       {
8421         guint32 version;
8422         guint32 offset;
8423
8424         if (length < 16) {
8425           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8426               GST_FOURCC_ARGS (fourcc));
8427           break;
8428         }
8429
8430         version = QT_UINT32 (buffer + 12);
8431         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8432
8433         switch (version) {
8434           case 0x00000001:
8435             offset = 0x62;
8436             break;
8437           default:
8438             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8439             offset = 0;
8440             break;
8441         }
8442         if (offset) {
8443           if (length < offset) {
8444             GST_WARNING_OBJECT (qtdemux,
8445                 "skipping too small %" GST_FOURCC_FORMAT " box",
8446                 GST_FOURCC_ARGS (fourcc));
8447             break;
8448           }
8449           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8450         }
8451         break;
8452       }
8453       case FOURCC_in24:
8454       {
8455         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8456         break;
8457       }
8458       case FOURCC_uuid:
8459       {
8460         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8461         break;
8462       }
8463       case FOURCC_enca:
8464       {
8465         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8466         break;
8467       }
8468       default:
8469         if (!strcmp (type->name, "unknown"))
8470           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8471         break;
8472     }
8473   }
8474   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8475       GST_FOURCC_ARGS (fourcc));
8476   return TRUE;
8477
8478 /* ERRORS */
8479 not_enough_data:
8480   {
8481     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8482         (_("This file is corrupt and cannot be played.")),
8483         ("Not enough data for an atom header, got only %u bytes", length));
8484     return FALSE;
8485   }
8486 broken_atom_size:
8487   {
8488     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8489         (_("This file is corrupt and cannot be played.")),
8490         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8491             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8492             length));
8493     return FALSE;
8494   }
8495 }
8496
8497 static void
8498 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8499 {
8500 /* FIXME: This can only reliably work if demuxers have a
8501  * separate streaming thread per srcpad. This should be
8502  * done in a demuxer base class, which integrates parts
8503  * of multiqueue
8504  *
8505  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8506  */
8507 #if 0
8508   GstQuery *query;
8509
8510   query = gst_query_new_allocation (stream->caps, FALSE);
8511
8512   if (!gst_pad_peer_query (stream->pad, query)) {
8513     /* not a problem, just debug a little */
8514     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8515   }
8516
8517   if (stream->allocator)
8518     gst_object_unref (stream->allocator);
8519
8520   if (gst_query_get_n_allocation_params (query) > 0) {
8521     /* try the allocator */
8522     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8523         &stream->params);
8524     stream->use_allocator = TRUE;
8525   } else {
8526     stream->allocator = NULL;
8527     gst_allocation_params_init (&stream->params);
8528     stream->use_allocator = FALSE;
8529   }
8530   gst_query_unref (query);
8531 #endif
8532 }
8533
8534 static gboolean
8535 pad_query (const GValue * item, GValue * value, gpointer user_data)
8536 {
8537   GstPad *pad = g_value_get_object (item);
8538   GstQuery *query = user_data;
8539   gboolean res;
8540
8541   res = gst_pad_peer_query (pad, query);
8542
8543   if (res) {
8544     g_value_set_boolean (value, TRUE);
8545     return FALSE;
8546   }
8547
8548   GST_INFO_OBJECT (pad, "pad peer query failed");
8549   return TRUE;
8550 }
8551
8552 static gboolean
8553 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8554     GstPadDirection direction)
8555 {
8556   GstIterator *it;
8557   GstIteratorFoldFunction func = pad_query;
8558   GValue res = { 0, };
8559
8560   g_value_init (&res, G_TYPE_BOOLEAN);
8561   g_value_set_boolean (&res, FALSE);
8562
8563   /* Ask neighbor */
8564   if (direction == GST_PAD_SRC)
8565     it = gst_element_iterate_src_pads (element);
8566   else
8567     it = gst_element_iterate_sink_pads (element);
8568
8569   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8570     gst_iterator_resync (it);
8571
8572   gst_iterator_free (it);
8573
8574   return g_value_get_boolean (&res);
8575 }
8576
8577 static void
8578 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8579     QtDemuxStream * stream)
8580 {
8581   GstQuery *query;
8582   GstContext *ctxt;
8583   GstElement *element = GST_ELEMENT (qtdemux);
8584   GstStructure *st;
8585   gchar **filtered_sys_ids;
8586   GValue event_list = G_VALUE_INIT;
8587   GList *walk;
8588
8589   /* 1. Check if we already have the context. */
8590   if (qtdemux->preferred_protection_system_id != NULL) {
8591     GST_LOG_OBJECT (element,
8592         "already have the protection context, no need to request it again");
8593     return;
8594   }
8595
8596   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8597   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8598       (const gchar **) qtdemux->protection_system_ids->pdata);
8599
8600   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8601       qtdemux->protection_system_ids->len - 1);
8602   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8603       "decryptors for %u of them, running context request",
8604       qtdemux->protection_system_ids->len,
8605       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8606
8607
8608   if (stream->protection_scheme_event_queue.length) {
8609     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8610         stream->protection_scheme_event_queue.length);
8611     walk = stream->protection_scheme_event_queue.tail;
8612   } else {
8613     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8614         qtdemux->protection_event_queue.length);
8615     walk = qtdemux->protection_event_queue.tail;
8616   }
8617
8618   g_value_init (&event_list, GST_TYPE_LIST);
8619   for (; walk; walk = g_list_previous (walk)) {
8620     GValue event_value = G_VALUE_INIT;
8621     g_value_init (&event_value, GST_TYPE_EVENT);
8622     g_value_set_boxed (&event_value, walk->data);
8623     gst_value_list_append_and_take_value (&event_list, &event_value);
8624   }
8625
8626   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8627    *      check if downstream already has a context of the specific type
8628    *  2b) Query upstream as above.
8629    */
8630   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8631   st = gst_query_writable_structure (query);
8632   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8633       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8634       NULL);
8635   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8636   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8637     gst_query_parse_context (query, &ctxt);
8638     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8639     gst_element_set_context (element, ctxt);
8640   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8641     gst_query_parse_context (query, &ctxt);
8642     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8643     gst_element_set_context (element, ctxt);
8644   } else {
8645     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8646      *    the required context type and afterwards check if a
8647      *    usable context was set now as in 1). The message could
8648      *    be handled by the parent bins of the element and the
8649      *    application.
8650      */
8651     GstMessage *msg;
8652
8653     GST_INFO_OBJECT (element, "posting need context message");
8654     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8655         "drm-preferred-decryption-system-id");
8656     st = (GstStructure *) gst_message_get_structure (msg);
8657     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8658         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8659         NULL);
8660
8661     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8662     gst_element_post_message (element, msg);
8663   }
8664
8665   g_strfreev (filtered_sys_ids);
8666   g_value_unset (&event_list);
8667   gst_query_unref (query);
8668 }
8669
8670 static gboolean
8671 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8672     QtDemuxStream * stream)
8673 {
8674   GstStructure *s;
8675   const gchar *selected_system = NULL;
8676
8677   g_return_val_if_fail (qtdemux != NULL, FALSE);
8678   g_return_val_if_fail (stream != NULL, FALSE);
8679   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8680       FALSE);
8681
8682   if (stream->protection_scheme_type == FOURCC_aavd) {
8683     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8684     if (!gst_structure_has_name (s, "application/x-aavd")) {
8685       gst_structure_set (s,
8686           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8687           NULL);
8688       gst_structure_set_name (s, "application/x-aavd");
8689     }
8690     return TRUE;
8691   }
8692
8693   if (stream->protection_scheme_type != FOURCC_cenc
8694       && stream->protection_scheme_type != FOURCC_cbcs) {
8695     GST_ERROR_OBJECT (qtdemux,
8696         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8697         GST_FOURCC_ARGS (stream->protection_scheme_type));
8698     return FALSE;
8699   }
8700
8701   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8702   if (!gst_structure_has_name (s, "application/x-cenc")) {
8703     gst_structure_set (s,
8704         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8705     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8706         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8707         NULL);
8708     gst_structure_set_name (s, "application/x-cenc");
8709   }
8710
8711   if (qtdemux->protection_system_ids == NULL) {
8712     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8713         "cenc protection system information has been found, not setting a "
8714         "protection system UUID");
8715     return TRUE;
8716   }
8717
8718   gst_qtdemux_request_protection_context (qtdemux, stream);
8719   if (qtdemux->preferred_protection_system_id != NULL) {
8720     const gchar *preferred_system_array[] =
8721         { qtdemux->preferred_protection_system_id, NULL };
8722
8723     selected_system = gst_protection_select_system (preferred_system_array);
8724
8725     if (selected_system) {
8726       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8727           qtdemux->preferred_protection_system_id);
8728     } else {
8729       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8730           "because there is no available decryptor",
8731           qtdemux->preferred_protection_system_id);
8732     }
8733   }
8734
8735   if (!selected_system) {
8736     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8737     selected_system = gst_protection_select_system ((const gchar **)
8738         qtdemux->protection_system_ids->pdata);
8739     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8740         qtdemux->protection_system_ids->len - 1);
8741   }
8742
8743   if (!selected_system) {
8744     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8745         "suitable decryptor element has been found");
8746     return FALSE;
8747   }
8748
8749   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8750       selected_system);
8751
8752   gst_structure_set (s,
8753       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8754       NULL);
8755
8756   return TRUE;
8757 }
8758
8759 static gboolean
8760 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8761 {
8762   /* fps is calculated base on the duration of the average framerate since
8763    * qt does not have a fixed framerate. */
8764   gboolean fps_available = TRUE;
8765   guint32 first_duration = 0;
8766
8767   if (stream->n_samples > 0)
8768     first_duration = stream->samples[0].duration;
8769
8770   if ((stream->n_samples == 1 && first_duration == 0)
8771       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8772     /* still frame */
8773     CUR_STREAM (stream)->fps_n = 0;
8774     CUR_STREAM (stream)->fps_d = 1;
8775   } else {
8776     if (stream->duration == 0 || stream->n_samples < 2) {
8777       CUR_STREAM (stream)->fps_n = stream->timescale;
8778       CUR_STREAM (stream)->fps_d = 1;
8779       fps_available = FALSE;
8780     } else {
8781       GstClockTime avg_duration;
8782       guint64 duration;
8783       guint32 n_samples;
8784
8785       /* duration and n_samples can be updated for fragmented format
8786        * so, framerate of fragmented format is calculated using data in a moof */
8787       if (qtdemux->fragmented && stream->n_samples_moof > 0
8788           && stream->duration_moof > 0) {
8789         n_samples = stream->n_samples_moof;
8790         duration = stream->duration_moof;
8791       } else {
8792         n_samples = stream->n_samples;
8793         duration = stream->duration;
8794       }
8795
8796       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8797       /* stream->duration is guint64, timescale, n_samples are guint32 */
8798       avg_duration =
8799           gst_util_uint64_scale_round (duration -
8800           first_duration, GST_SECOND,
8801           (guint64) (stream->timescale) * (n_samples - 1));
8802
8803       GST_LOG_OBJECT (qtdemux,
8804           "Calculating avg sample duration based on stream (or moof) duration %"
8805           G_GUINT64_FORMAT
8806           " minus first sample %u, leaving %d samples gives %"
8807           GST_TIME_FORMAT, duration, first_duration,
8808           n_samples - 1, GST_TIME_ARGS (avg_duration));
8809
8810       fps_available =
8811           gst_video_guess_framerate (avg_duration,
8812           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8813
8814       GST_DEBUG_OBJECT (qtdemux,
8815           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8816           stream->timescale, CUR_STREAM (stream)->fps_n,
8817           CUR_STREAM (stream)->fps_d);
8818     }
8819   }
8820
8821   return fps_available;
8822 }
8823
8824 static gboolean
8825 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8826 {
8827   if (stream->subtype == FOURCC_vide) {
8828     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8829
8830     if (CUR_STREAM (stream)->caps) {
8831       CUR_STREAM (stream)->caps =
8832           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8833
8834       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8835         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8836             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8837             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8838
8839       /* set framerate if calculated framerate is reliable */
8840       if (fps_available) {
8841         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8842             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8843             CUR_STREAM (stream)->fps_d, NULL);
8844       }
8845
8846       /* calculate pixel-aspect-ratio using display width and height */
8847       GST_DEBUG_OBJECT (qtdemux,
8848           "video size %dx%d, target display size %dx%d",
8849           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8850           stream->display_width, stream->display_height);
8851       /* qt file might have pasp atom */
8852       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8853         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8854             CUR_STREAM (stream)->par_h);
8855         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8856             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8857             CUR_STREAM (stream)->par_h, NULL);
8858       } else if (stream->display_width > 0 && stream->display_height > 0
8859           && CUR_STREAM (stream)->width > 0
8860           && CUR_STREAM (stream)->height > 0) {
8861         gint n, d;
8862
8863         /* calculate the pixel aspect ratio using the display and pixel w/h */
8864         n = stream->display_width * CUR_STREAM (stream)->height;
8865         d = stream->display_height * CUR_STREAM (stream)->width;
8866         if (n == d)
8867           n = d = 1;
8868         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8869         CUR_STREAM (stream)->par_w = n;
8870         CUR_STREAM (stream)->par_h = d;
8871         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8872             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8873             CUR_STREAM (stream)->par_h, NULL);
8874       }
8875
8876       if (CUR_STREAM (stream)->interlace_mode > 0) {
8877         if (CUR_STREAM (stream)->interlace_mode == 1) {
8878           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8879               G_TYPE_STRING, "progressive", NULL);
8880         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8881           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8882               G_TYPE_STRING, "interleaved", NULL);
8883           if (CUR_STREAM (stream)->field_order == 9) {
8884             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8885                 G_TYPE_STRING, "top-field-first", NULL);
8886           } else if (CUR_STREAM (stream)->field_order == 14) {
8887             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8888                 G_TYPE_STRING, "bottom-field-first", NULL);
8889           }
8890         }
8891       }
8892
8893       /* Create incomplete colorimetry here if needed */
8894       if (CUR_STREAM (stream)->colorimetry.range ||
8895           CUR_STREAM (stream)->colorimetry.matrix ||
8896           CUR_STREAM (stream)->colorimetry.transfer
8897           || CUR_STREAM (stream)->colorimetry.primaries) {
8898         gchar *colorimetry =
8899             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8900         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8901             G_TYPE_STRING, colorimetry, NULL);
8902         g_free (colorimetry);
8903       }
8904
8905       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8906         guint par_w = 1, par_h = 1;
8907
8908         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8909           par_w = CUR_STREAM (stream)->par_w;
8910           par_h = CUR_STREAM (stream)->par_h;
8911         }
8912
8913         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8914                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8915                 par_h)) {
8916           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8917         }
8918
8919         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8920             "multiview-mode", G_TYPE_STRING,
8921             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8922             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8923             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8924       }
8925     }
8926   }
8927
8928   else if (stream->subtype == FOURCC_soun) {
8929     if (CUR_STREAM (stream)->caps) {
8930       CUR_STREAM (stream)->caps =
8931           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8932       if (CUR_STREAM (stream)->rate > 0)
8933         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8934             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8935       if (CUR_STREAM (stream)->n_channels > 0)
8936         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8937             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8938       if (CUR_STREAM (stream)->n_channels > 2) {
8939         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8940          * correctly; this is just the minimum we can do - assume
8941          * we don't actually have any channel positions. */
8942         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8943             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8944       }
8945     }
8946   }
8947
8948   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8949     const GstStructure *s;
8950     QtDemuxStream *fps_stream = NULL;
8951     gboolean fps_available = FALSE;
8952
8953     /* CEA608 closed caption tracks are a bit special in that each sample
8954      * can contain CCs for multiple frames, and CCs can be omitted and have to
8955      * be inferred from the duration of the sample then.
8956      *
8957      * As such we take the framerate from the (first) video track here for
8958      * CEA608 as there must be one CC byte pair for every video frame
8959      * according to the spec.
8960      *
8961      * For CEA708 all is fine and there is one sample per frame.
8962      */
8963
8964     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8965     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8966       gint i;
8967
8968       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8969         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8970
8971         if (tmp->subtype == FOURCC_vide) {
8972           fps_stream = tmp;
8973           break;
8974         }
8975       }
8976
8977       if (fps_stream) {
8978         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8979         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8980         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8981       }
8982     } else {
8983       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8984       fps_stream = stream;
8985     }
8986
8987     CUR_STREAM (stream)->caps =
8988         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8989
8990     /* set framerate if calculated framerate is reliable */
8991     if (fps_available) {
8992       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8993           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8994           CUR_STREAM (stream)->fps_d, NULL);
8995     }
8996   }
8997
8998   if (stream->pad) {
8999     gboolean forward_collection = FALSE;
9000     GstCaps *prev_caps = NULL;
9001
9002     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
9003     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
9004     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
9005     gst_pad_set_active (stream->pad, TRUE);
9006
9007     gst_pad_use_fixed_caps (stream->pad);
9008
9009     if (stream->protected) {
9010       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
9011         GST_ERROR_OBJECT (qtdemux,
9012             "Failed to configure protected stream caps.");
9013         return FALSE;
9014       }
9015     }
9016
9017     if (stream->new_stream) {
9018       GstEvent *event;
9019       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
9020
9021       event =
9022           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
9023           0);
9024       if (event) {
9025         gst_event_parse_stream_flags (event, &stream_flags);
9026         if (gst_event_parse_group_id (event, &qtdemux->group_id))
9027           qtdemux->have_group_id = TRUE;
9028         else
9029           qtdemux->have_group_id = FALSE;
9030         gst_event_unref (event);
9031       } else if (!qtdemux->have_group_id) {
9032         qtdemux->have_group_id = TRUE;
9033         qtdemux->group_id = gst_util_group_id_next ();
9034       }
9035
9036       stream->new_stream = FALSE;
9037       event = gst_event_new_stream_start (stream->stream_id);
9038       if (qtdemux->have_group_id)
9039         gst_event_set_group_id (event, qtdemux->group_id);
9040       if (stream->disabled)
9041         stream_flags |= GST_STREAM_FLAG_UNSELECT;
9042       if (CUR_STREAM (stream)->sparse) {
9043         stream_flags |= GST_STREAM_FLAG_SPARSE;
9044       } else {
9045         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
9046       }
9047       gst_event_set_stream_flags (event, stream_flags);
9048       gst_pad_push_event (stream->pad, event);
9049
9050       forward_collection = TRUE;
9051     }
9052
9053     prev_caps = gst_pad_get_current_caps (stream->pad);
9054
9055     if (CUR_STREAM (stream)->caps) {
9056       if (!prev_caps
9057           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
9058         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
9059             CUR_STREAM (stream)->caps);
9060         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
9061       } else {
9062         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
9063       }
9064     } else {
9065       GST_WARNING_OBJECT (qtdemux, "stream without caps");
9066     }
9067
9068     if (prev_caps)
9069       gst_caps_unref (prev_caps);
9070     stream->new_caps = FALSE;
9071
9072     if (forward_collection) {
9073       /* Forward upstream collection and selection if any */
9074       GstEvent *upstream_event = gst_pad_get_sticky_event (qtdemux->sinkpad,
9075           GST_EVENT_STREAM_COLLECTION, 0);
9076       if (upstream_event)
9077         gst_pad_push_event (stream->pad, upstream_event);
9078     }
9079   }
9080   return TRUE;
9081 }
9082
9083 static void
9084 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
9085     QtDemuxStream * stream)
9086 {
9087   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
9088     return;
9089
9090   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
9091       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
9092   if (G_UNLIKELY (stream->stsd_sample_description_id >=
9093           stream->stsd_entries_length)) {
9094     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
9095         (_("This file is invalid and cannot be played.")),
9096         ("New sample description id is out of bounds (%d >= %d)",
9097             stream->stsd_sample_description_id, stream->stsd_entries_length));
9098   } else {
9099     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
9100     stream->new_caps = TRUE;
9101   }
9102 }
9103
9104 static gboolean
9105 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
9106     QtDemuxStream * stream, GstTagList * list)
9107 {
9108   gboolean ret = TRUE;
9109
9110   if (stream->subtype == FOURCC_vide) {
9111     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9112
9113     stream->pad =
9114         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9115     g_free (name);
9116
9117     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9118       gst_object_unref (stream->pad);
9119       stream->pad = NULL;
9120       ret = FALSE;
9121       goto done;
9122     }
9123
9124     qtdemux->n_video_streams++;
9125   } else if (stream->subtype == FOURCC_soun) {
9126     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
9127
9128     stream->pad =
9129         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
9130     g_free (name);
9131     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9132       gst_object_unref (stream->pad);
9133       stream->pad = NULL;
9134       ret = FALSE;
9135       goto done;
9136     }
9137     qtdemux->n_audio_streams++;
9138   } else if (stream->subtype == FOURCC_strm) {
9139     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
9140   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
9141       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
9142       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
9143     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
9144
9145     stream->pad =
9146         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
9147     g_free (name);
9148     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9149       gst_object_unref (stream->pad);
9150       stream->pad = NULL;
9151       ret = FALSE;
9152       goto done;
9153     }
9154     qtdemux->n_sub_streams++;
9155   } else if (stream->subtype == FOURCC_meta) {
9156     gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
9157
9158     stream->pad =
9159         gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
9160     g_free (name);
9161     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9162       gst_object_unref (stream->pad);
9163       stream->pad = NULL;
9164       ret = FALSE;
9165       goto done;
9166     }
9167     qtdemux->n_meta_streams++;
9168   } else if (CUR_STREAM (stream)->caps) {
9169     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
9170
9171     stream->pad =
9172         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
9173     g_free (name);
9174     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
9175       gst_object_unref (stream->pad);
9176       stream->pad = NULL;
9177       ret = FALSE;
9178       goto done;
9179     }
9180     qtdemux->n_video_streams++;
9181   } else {
9182     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
9183     goto done;
9184   }
9185
9186   if (stream->pad) {
9187     GList *l;
9188
9189     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
9190         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
9191     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
9192     GST_OBJECT_LOCK (qtdemux);
9193     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
9194     GST_OBJECT_UNLOCK (qtdemux);
9195
9196     if (stream->stream_tags)
9197       gst_tag_list_unref (stream->stream_tags);
9198     stream->stream_tags = list;
9199     list = NULL;
9200     /* global tags go on each pad anyway */
9201     stream->send_global_tags = TRUE;
9202     /* send upstream GST_EVENT_PROTECTION events that were received before
9203        this source pad was created */
9204     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
9205       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
9206   }
9207 done:
9208   if (list)
9209     gst_tag_list_unref (list);
9210   return ret;
9211 }
9212
9213 /* find next atom with @fourcc starting at @offset */
9214 static GstFlowReturn
9215 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
9216     guint64 * length, guint32 fourcc)
9217 {
9218   GstFlowReturn ret;
9219   guint32 lfourcc;
9220   GstBuffer *buf;
9221
9222   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
9223       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9224
9225   while (TRUE) {
9226     GstMapInfo map;
9227
9228     buf = NULL;
9229     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
9230     if (G_UNLIKELY (ret != GST_FLOW_OK))
9231       goto locate_failed;
9232     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
9233       /* likely EOF */
9234       ret = GST_FLOW_EOS;
9235       gst_buffer_unref (buf);
9236       goto locate_failed;
9237     }
9238     gst_buffer_map (buf, &map, GST_MAP_READ);
9239     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
9240     gst_buffer_unmap (buf, &map);
9241     gst_buffer_unref (buf);
9242
9243     if (G_UNLIKELY (*length == 0)) {
9244       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
9245       ret = GST_FLOW_ERROR;
9246       goto locate_failed;
9247     }
9248
9249     if (lfourcc == fourcc) {
9250       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
9251           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
9252       break;
9253     } else {
9254       GST_LOG_OBJECT (qtdemux,
9255           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
9256           GST_FOURCC_ARGS (lfourcc), *offset);
9257       if (*offset == G_MAXUINT64)
9258         goto locate_failed;
9259       *offset += *length;
9260     }
9261   }
9262
9263   return GST_FLOW_OK;
9264
9265 locate_failed:
9266   {
9267     /* might simply have had last one */
9268     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9269     return ret;
9270   }
9271 }
9272
9273 /* should only do something in pull mode */
9274 /* call with OBJECT lock */
9275 static GstFlowReturn
9276 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9277 {
9278   guint64 length, offset;
9279   GstBuffer *buf = NULL;
9280   GstFlowReturn ret = GST_FLOW_OK;
9281   GstFlowReturn res = GST_FLOW_OK;
9282   GstMapInfo map;
9283
9284   offset = qtdemux->moof_offset;
9285   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9286
9287   if (!offset) {
9288     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9289     return GST_FLOW_EOS;
9290   }
9291
9292   /* best not do pull etc with lock held */
9293   GST_OBJECT_UNLOCK (qtdemux);
9294
9295   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9296   if (ret != GST_FLOW_OK)
9297     goto flow_failed;
9298
9299   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9300   if (G_UNLIKELY (ret != GST_FLOW_OK))
9301     goto flow_failed;
9302   gst_buffer_map (buf, &map, GST_MAP_READ);
9303   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9304     gst_buffer_unmap (buf, &map);
9305     gst_buffer_unref (buf);
9306     buf = NULL;
9307     goto parse_failed;
9308   }
9309
9310   gst_buffer_unmap (buf, &map);
9311   gst_buffer_unref (buf);
9312   buf = NULL;
9313
9314   offset += length;
9315   /* look for next moof */
9316   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9317   if (G_UNLIKELY (ret != GST_FLOW_OK))
9318     goto flow_failed;
9319
9320 exit:
9321   GST_OBJECT_LOCK (qtdemux);
9322
9323   qtdemux->moof_offset = offset;
9324
9325   return res;
9326
9327 parse_failed:
9328   {
9329     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9330     offset = 0;
9331     res = GST_FLOW_ERROR;
9332     goto exit;
9333   }
9334 flow_failed:
9335   {
9336     /* maybe upstream temporarily flushing */
9337     if (ret != GST_FLOW_FLUSHING) {
9338       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9339       offset = 0;
9340     } else {
9341       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9342       /* resume at current position next time */
9343     }
9344     res = ret;
9345     goto exit;
9346   }
9347 }
9348
9349 static void
9350 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9351 {
9352   guint i;
9353   guint32 num_chunks;
9354   gint32 stts_duration;
9355   GstByteWriter stsc, stts, stsz;
9356
9357   /* Each sample has a different size, which we don't support for merging */
9358   if (stream->sample_size == 0) {
9359     GST_DEBUG_OBJECT (qtdemux,
9360         "Not all samples have the same size, not merging");
9361     return;
9362   }
9363
9364   /* The stream has a ctts table, we don't support that */
9365   if (stream->ctts_present) {
9366     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9367     return;
9368   }
9369
9370   /* If there's a sync sample table also ignore this stream */
9371   if (stream->stps_present || stream->stss_present) {
9372     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9373     return;
9374   }
9375
9376   /* If chunks are considered samples already ignore this stream */
9377   if (stream->chunks_are_samples) {
9378     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9379     return;
9380   }
9381
9382   /* Require that all samples have the same duration */
9383   if (stream->n_sample_times > 1) {
9384     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9385     return;
9386   }
9387
9388   /* Parse the stts to get the sample duration and number of samples */
9389   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9390   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9391
9392   /* Parse the number of chunks from the stco manually because the
9393    * reader is already behind that */
9394   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9395
9396   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9397       num_chunks);
9398
9399   /* Now parse stsc, convert chunks into single samples and generate a
9400    * new stsc, stts and stsz from this information */
9401   gst_byte_writer_init (&stsc);
9402   gst_byte_writer_init (&stts);
9403   gst_byte_writer_init (&stsz);
9404
9405   /* Note: we skip fourccs, size, version, flags and other fields of the new
9406    * atoms as the byte readers with them are already behind that position
9407    * anyway and only update the values of those inside the stream directly.
9408    */
9409   stream->n_sample_times = 0;
9410   stream->n_samples = 0;
9411   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9412     guint j;
9413     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9414
9415     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9416     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9417     sample_description_id =
9418         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9419
9420     if (i == stream->n_samples_per_chunk - 1) {
9421       /* +1 because first_chunk is 1-based */
9422       last_chunk = num_chunks + 1;
9423     } else {
9424       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9425     }
9426
9427     GST_DEBUG_OBJECT (qtdemux,
9428         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9429         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9430
9431     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9432     /* One sample in this chunk */
9433     gst_byte_writer_put_uint32_be (&stsc, 1);
9434     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9435
9436     /* For each chunk write a stts and stsz entry now */
9437     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9438     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9439     for (j = first_chunk; j < last_chunk; j++) {
9440       gst_byte_writer_put_uint32_be (&stsz,
9441           stream->sample_size * samples_per_chunk);
9442     }
9443
9444     stream->n_sample_times += 1;
9445     stream->n_samples += last_chunk - first_chunk;
9446   }
9447
9448   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9449
9450   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9451       stream->n_samples, stream->n_sample_times);
9452
9453   /* We don't have a fixed sample size anymore */
9454   stream->sample_size = 0;
9455
9456   /* Free old data for the atoms */
9457   g_free ((gpointer) stream->stsz.data);
9458   stream->stsz.data = NULL;
9459   g_free ((gpointer) stream->stsc.data);
9460   stream->stsc.data = NULL;
9461   g_free ((gpointer) stream->stts.data);
9462   stream->stts.data = NULL;
9463
9464   /* Store new data and replace byte readers */
9465   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9466   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9467   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9468   stream->stts.size = gst_byte_writer_get_size (&stts);
9469   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9470   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9471   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9472   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9473   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9474 }
9475
9476 /* initialise bytereaders for stbl sub-atoms */
9477 static gboolean
9478 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9479 {
9480   stream->stbl_index = -1;      /* no samples have yet been parsed */
9481   stream->sample_index = -1;
9482
9483   /* time-to-sample atom */
9484   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9485     goto corrupt_file;
9486
9487   /* copy atom data into a new buffer for later use */
9488   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9489
9490   /* skip version + flags */
9491   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9492       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9493     goto corrupt_file;
9494   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9495
9496   /* make sure there's enough data */
9497   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9498     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9499     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9500         stream->n_sample_times);
9501     if (!stream->n_sample_times)
9502       goto corrupt_file;
9503   }
9504
9505   /* sync sample atom */
9506   stream->stps_present = FALSE;
9507   if ((stream->stss_present =
9508           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9509               &stream->stss) ? TRUE : FALSE) == TRUE) {
9510     /* copy atom data into a new buffer for later use */
9511     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9512
9513     /* skip version + flags */
9514     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9515         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9516       goto corrupt_file;
9517
9518     if (stream->n_sample_syncs) {
9519       /* make sure there's enough data */
9520       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9521         goto corrupt_file;
9522     }
9523
9524     /* partial sync sample atom */
9525     if ((stream->stps_present =
9526             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9527                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9528       /* copy atom data into a new buffer for later use */
9529       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9530
9531       /* skip version + flags */
9532       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9533           !gst_byte_reader_get_uint32_be (&stream->stps,
9534               &stream->n_sample_partial_syncs))
9535         goto corrupt_file;
9536
9537       /* if there are no entries, the stss table contains the real
9538        * sync samples */
9539       if (stream->n_sample_partial_syncs) {
9540         /* make sure there's enough data */
9541         if (!qt_atom_parser_has_chunks (&stream->stps,
9542                 stream->n_sample_partial_syncs, 4))
9543           goto corrupt_file;
9544       }
9545     }
9546   }
9547
9548   /* sample size */
9549   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9550     goto no_samples;
9551
9552   /* copy atom data into a new buffer for later use */
9553   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9554
9555   /* skip version + flags */
9556   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9557       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9558     goto corrupt_file;
9559
9560   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9561     goto corrupt_file;
9562
9563   if (!stream->n_samples)
9564     goto no_samples;
9565
9566   /* sample-to-chunk atom */
9567   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9568     goto corrupt_file;
9569
9570   /* copy atom data into a new buffer for later use */
9571   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9572
9573   /* skip version + flags */
9574   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9575       !gst_byte_reader_get_uint32_be (&stream->stsc,
9576           &stream->n_samples_per_chunk))
9577     goto corrupt_file;
9578
9579   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9580       stream->n_samples_per_chunk);
9581
9582   /* make sure there's enough data */
9583   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9584           12))
9585     goto corrupt_file;
9586
9587
9588   /* chunk offset */
9589   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9590     stream->co_size = sizeof (guint32);
9591   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9592           &stream->stco))
9593     stream->co_size = sizeof (guint64);
9594   else
9595     goto corrupt_file;
9596
9597   /* copy atom data into a new buffer for later use */
9598   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9599
9600   /* skip version + flags */
9601   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9602     goto corrupt_file;
9603
9604   /* chunks_are_samples == TRUE means treat chunks as samples */
9605   stream->chunks_are_samples = stream->sample_size
9606       && !CUR_STREAM (stream)->sampled;
9607   if (stream->chunks_are_samples) {
9608     /* treat chunks as samples */
9609     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9610       goto corrupt_file;
9611   } else {
9612     /* skip number of entries */
9613     if (!gst_byte_reader_skip (&stream->stco, 4))
9614       goto corrupt_file;
9615
9616     /* make sure there are enough data in the stsz atom */
9617     if (!stream->sample_size) {
9618       /* different sizes for each sample */
9619       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9620         goto corrupt_file;
9621     }
9622   }
9623
9624   /* composition time-to-sample */
9625   if ((stream->ctts_present =
9626           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9627               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9628     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9629     guint8 ctts_version;
9630     gboolean checked_ctts = FALSE;
9631
9632     /* copy atom data into a new buffer for later use */
9633     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9634
9635     /* version 1 has signed offsets */
9636     if (!gst_byte_reader_get_uint8 (&stream->ctts, &ctts_version))
9637       goto corrupt_file;
9638
9639     /* flags */
9640     if (!gst_byte_reader_skip (&stream->ctts, 3)
9641         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9642             &stream->n_composition_times))
9643       goto corrupt_file;
9644
9645     /* make sure there's enough data */
9646     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9647             4 + 4))
9648       goto corrupt_file;
9649
9650     /* This is optional, if missing we iterate the ctts */
9651     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9652       guint8 cslg_version;
9653
9654       /* cslg version 1 has 64 bit fields */
9655       if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
9656         goto corrupt_file;
9657
9658       /* skip flags */
9659       if (!gst_byte_reader_skip (&cslg, 3))
9660         goto corrupt_file;
9661
9662       if (cslg_version == 0) {
9663         gint32 composition_to_dts_shift;
9664
9665         if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
9666           goto corrupt_file;
9667
9668         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9669       } else {
9670         gint64 composition_to_dts_shift;
9671
9672         if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
9673           goto corrupt_file;
9674
9675         stream->cslg_shift = MAX (0, composition_to_dts_shift);
9676       }
9677     } else {
9678       gint32 cslg_least = 0;
9679       guint num_entries, pos;
9680       gint i;
9681
9682       pos = gst_byte_reader_get_pos (&stream->ctts);
9683       num_entries = stream->n_composition_times;
9684
9685       checked_ctts = TRUE;
9686
9687       stream->cslg_shift = 0;
9688
9689       for (i = 0; i < num_entries; i++) {
9690         gint32 offset;
9691
9692         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9693         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9694         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9695          * slightly inaccurate PTS could be more usable than corrupted one */
9696         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9697                 && ABS (offset) / 2 > stream->duration)) {
9698           GST_WARNING_OBJECT (qtdemux,
9699               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9700               " larger than duration %" G_GUINT64_FORMAT, offset,
9701               stream->duration);
9702
9703           stream->cslg_shift = 0;
9704           stream->ctts_present = FALSE;
9705           goto done;
9706         }
9707
9708         /* Don't consider "no decode samples" with offset G_MININT32
9709          * for the DTS/PTS shift */
9710         if (offset != G_MININT32 && offset < cslg_least)
9711           cslg_least = offset;
9712       }
9713
9714       if (cslg_least < 0)
9715         stream->cslg_shift = -cslg_least;
9716       else
9717         stream->cslg_shift = 0;
9718
9719       /* reset the reader so we can generate sample table */
9720       gst_byte_reader_set_pos (&stream->ctts, pos);
9721     }
9722
9723     /* Check if ctts values are looking reasonable if that didn't happen above */
9724     if (!checked_ctts) {
9725       guint num_entries, pos;
9726       gint i;
9727
9728       pos = gst_byte_reader_get_pos (&stream->ctts);
9729       num_entries = stream->n_composition_times;
9730
9731       for (i = 0; i < num_entries; i++) {
9732         gint32 offset;
9733
9734         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9735         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9736         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9737          * slightly inaccurate PTS could be more usable than corrupted one */
9738         if (G_UNLIKELY ((ctts_version == 0 || offset != G_MININT32)
9739                 && ABS (offset) / 2 > stream->duration)) {
9740           GST_WARNING_OBJECT (qtdemux,
9741               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9742               " larger than duration %" G_GUINT64_FORMAT, offset,
9743               stream->duration);
9744
9745           stream->cslg_shift = 0;
9746           stream->ctts_present = FALSE;
9747           goto done;
9748         }
9749       }
9750
9751       /* reset the reader so we can generate sample table */
9752       gst_byte_reader_set_pos (&stream->ctts, pos);
9753     }
9754   } else {
9755     /* Ensure the cslg_shift value is consistent so we can use it
9756      * unconditionally to produce TS and Segment */
9757     stream->cslg_shift = 0;
9758   }
9759
9760   GST_DEBUG_OBJECT (qtdemux, "Using clsg_shift %" G_GUINT64_FORMAT,
9761       stream->cslg_shift);
9762
9763   /* For raw audio streams especially we might want to merge the samples
9764    * to not output one audio sample per buffer. We're doing this here
9765    * before allocating the sample tables so that from this point onwards
9766    * the number of container samples are static */
9767   if (stream->min_buffer_size > 0) {
9768     qtdemux_merge_sample_table (qtdemux, stream);
9769   }
9770
9771 done:
9772   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9773       stream->n_samples, (guint) sizeof (QtDemuxSample),
9774       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9775
9776   if (stream->n_samples >=
9777       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9778     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9779         "be larger than %uMB (broken file?)", stream->n_samples,
9780         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9781     return FALSE;
9782   }
9783
9784   g_assert (stream->samples == NULL);
9785   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9786   if (!stream->samples) {
9787     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9788         stream->n_samples);
9789     return FALSE;
9790   }
9791
9792   return TRUE;
9793
9794 corrupt_file:
9795   {
9796     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9797         (_("This file is corrupt and cannot be played.")), (NULL));
9798     return FALSE;
9799   }
9800 no_samples:
9801   {
9802     gst_qtdemux_stbl_free (stream);
9803     if (!qtdemux->fragmented) {
9804       /* not quite good */
9805       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9806       return FALSE;
9807     } else {
9808       /* may pick up samples elsewhere */
9809       return TRUE;
9810     }
9811   }
9812 }
9813
9814 /* collect samples from the next sample to be parsed up to sample @n for @stream
9815  * by reading the info from @stbl
9816  *
9817  * This code can be executed from both the streaming thread and the seeking
9818  * thread so it takes the object lock to protect itself
9819  */
9820 static gboolean
9821 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9822 {
9823   gint i, j, k;
9824   QtDemuxSample *samples, *first, *cur, *last;
9825   guint32 n_samples_per_chunk;
9826   guint32 n_samples;
9827
9828   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9829       GST_FOURCC_FORMAT ", pad %s",
9830       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9831       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9832
9833   n_samples = stream->n_samples;
9834
9835   if (n >= n_samples)
9836     goto out_of_samples;
9837
9838   GST_OBJECT_LOCK (qtdemux);
9839   if (n <= stream->stbl_index)
9840     goto already_parsed;
9841
9842   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9843
9844   if (!stream->stsz.data) {
9845     /* so we already parsed and passed all the moov samples;
9846      * onto fragmented ones */
9847     g_assert (qtdemux->fragmented);
9848     goto done;
9849   }
9850
9851   /* pointer to the sample table */
9852   samples = stream->samples;
9853
9854   /* starts from -1, moves to the next sample index to parse */
9855   stream->stbl_index++;
9856
9857   /* keep track of the first and last sample to fill */
9858   first = &samples[stream->stbl_index];
9859   last = &samples[n];
9860
9861   if (!stream->chunks_are_samples) {
9862     /* set the sample sizes */
9863     if (stream->sample_size == 0) {
9864       /* different sizes for each sample */
9865       for (cur = first; cur <= last; cur++) {
9866         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9867         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9868             (guint) (cur - samples), cur->size);
9869       }
9870     } else {
9871       /* samples have the same size */
9872       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9873       for (cur = first; cur <= last; cur++)
9874         cur->size = stream->sample_size;
9875     }
9876   }
9877
9878   n_samples_per_chunk = stream->n_samples_per_chunk;
9879   cur = first;
9880
9881   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9882     guint32 last_chunk;
9883
9884     if (stream->stsc_chunk_index >= stream->last_chunk
9885         || stream->stsc_chunk_index < stream->first_chunk) {
9886       stream->first_chunk =
9887           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9888       stream->samples_per_chunk =
9889           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9890       /* starts from 1 */
9891       stream->stsd_sample_description_id =
9892           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9893
9894       /* chunk numbers are counted from 1 it seems */
9895       if (G_UNLIKELY (stream->first_chunk == 0))
9896         goto corrupt_file;
9897
9898       --stream->first_chunk;
9899
9900       /* the last chunk of each entry is calculated by taking the first chunk
9901        * of the next entry; except if there is no next, where we fake it with
9902        * INT_MAX */
9903       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9904         stream->last_chunk = G_MAXUINT32;
9905       } else {
9906         stream->last_chunk =
9907             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9908         if (G_UNLIKELY (stream->last_chunk == 0))
9909           goto corrupt_file;
9910
9911         --stream->last_chunk;
9912       }
9913
9914       GST_LOG_OBJECT (qtdemux,
9915           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9916           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9917           stream->samples_per_chunk, stream->stsd_sample_description_id);
9918
9919       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9920         goto corrupt_file;
9921
9922       if (stream->last_chunk != G_MAXUINT32) {
9923         if (!qt_atom_parser_peek_sub (&stream->stco,
9924                 stream->first_chunk * stream->co_size,
9925                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9926                 &stream->co_chunk))
9927           goto corrupt_file;
9928
9929       } else {
9930         stream->co_chunk = stream->stco;
9931         if (!gst_byte_reader_skip (&stream->co_chunk,
9932                 stream->first_chunk * stream->co_size))
9933           goto corrupt_file;
9934       }
9935
9936       stream->stsc_chunk_index = stream->first_chunk;
9937     }
9938
9939     last_chunk = stream->last_chunk;
9940
9941     if (stream->chunks_are_samples) {
9942       cur = &samples[stream->stsc_chunk_index];
9943
9944       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9945         if (j > n) {
9946           /* save state */
9947           stream->stsc_chunk_index = j;
9948           goto done;
9949         }
9950
9951         cur->offset =
9952             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9953             stream->co_size);
9954
9955         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9956             "%" G_GUINT64_FORMAT, j, cur->offset);
9957
9958         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9959             CUR_STREAM (stream)->bytes_per_frame > 0) {
9960           cur->size =
9961               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9962               CUR_STREAM (stream)->samples_per_frame *
9963               CUR_STREAM (stream)->bytes_per_frame;
9964         } else {
9965           cur->size = stream->samples_per_chunk;
9966         }
9967
9968         GST_DEBUG_OBJECT (qtdemux,
9969             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9970             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9971                     stream->stco_sample_index)), cur->size);
9972
9973         cur->timestamp = stream->stco_sample_index;
9974         cur->duration = stream->samples_per_chunk;
9975         cur->keyframe = TRUE;
9976         cur++;
9977
9978         stream->stco_sample_index += stream->samples_per_chunk;
9979       }
9980       stream->stsc_chunk_index = j;
9981     } else {
9982       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9983         guint32 samples_per_chunk;
9984         guint64 chunk_offset;
9985
9986         if (!stream->stsc_sample_index
9987             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9988                 &stream->chunk_offset))
9989           goto corrupt_file;
9990
9991         samples_per_chunk = stream->samples_per_chunk;
9992         chunk_offset = stream->chunk_offset;
9993
9994         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9995           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9996               G_GUINT64_FORMAT " and size %d",
9997               (guint) (cur - samples), chunk_offset, cur->size);
9998
9999           cur->offset = chunk_offset;
10000           chunk_offset += cur->size;
10001           cur++;
10002
10003           if (G_UNLIKELY (cur > last)) {
10004             /* save state */
10005             stream->stsc_sample_index = k + 1;
10006             stream->chunk_offset = chunk_offset;
10007             stream->stsc_chunk_index = j;
10008             goto done2;
10009           }
10010         }
10011         stream->stsc_sample_index = 0;
10012       }
10013       stream->stsc_chunk_index = j;
10014     }
10015     stream->stsc_index++;
10016   }
10017
10018   if (stream->chunks_are_samples)
10019     goto ctts;
10020 done2:
10021   {
10022     guint32 n_sample_times;
10023
10024     n_sample_times = stream->n_sample_times;
10025     cur = first;
10026
10027     for (i = stream->stts_index; i < n_sample_times; i++) {
10028       guint32 stts_samples;
10029       gint32 stts_duration;
10030       gint64 stts_time;
10031
10032       if (stream->stts_sample_index >= stream->stts_samples
10033           || !stream->stts_sample_index) {
10034
10035         stream->stts_samples =
10036             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10037         stream->stts_duration =
10038             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
10039
10040         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
10041             i, stream->stts_samples, stream->stts_duration);
10042
10043         stream->stts_sample_index = 0;
10044       }
10045
10046       stts_samples = stream->stts_samples;
10047       stts_duration = stream->stts_duration;
10048       stts_time = stream->stts_time;
10049
10050       for (j = stream->stts_sample_index; j < stts_samples; j++) {
10051         GST_DEBUG_OBJECT (qtdemux,
10052             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
10053             (guint) (cur - samples), j,
10054             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
10055
10056         cur->timestamp = stts_time;
10057         cur->duration = stts_duration;
10058
10059         /* avoid 32-bit wrap-around,
10060          * but still mind possible 'negative' duration */
10061         stts_time += (gint64) stts_duration;
10062         cur++;
10063
10064         if (G_UNLIKELY (cur > last)) {
10065           /* save values */
10066           stream->stts_time = stts_time;
10067           stream->stts_sample_index = j + 1;
10068           if (stream->stts_sample_index >= stream->stts_samples)
10069             stream->stts_index++;
10070           goto done3;
10071         }
10072       }
10073       stream->stts_sample_index = 0;
10074       stream->stts_time = stts_time;
10075       stream->stts_index++;
10076     }
10077     /* fill up empty timestamps with the last timestamp, this can happen when
10078      * the last samples do not decode and so we don't have timestamps for them.
10079      * We however look at the last timestamp to estimate the track length so we
10080      * need something in here. */
10081     for (; cur < last; cur++) {
10082       GST_DEBUG_OBJECT (qtdemux,
10083           "fill sample %d: timestamp %" GST_TIME_FORMAT,
10084           (guint) (cur - samples),
10085           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
10086       cur->timestamp = stream->stts_time;
10087       cur->duration = -1;
10088     }
10089   }
10090 done3:
10091   {
10092     /* sample sync, can be NULL */
10093     if (stream->stss_present == TRUE) {
10094       guint32 n_sample_syncs;
10095
10096       n_sample_syncs = stream->n_sample_syncs;
10097
10098       if (!n_sample_syncs) {
10099         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
10100         stream->all_keyframe = TRUE;
10101       } else {
10102         for (i = stream->stss_index; i < n_sample_syncs; i++) {
10103           /* note that the first sample is index 1, not 0 */
10104           guint32 index;
10105
10106           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
10107
10108           if (G_LIKELY (index > 0 && index <= n_samples)) {
10109             index -= 1;
10110             samples[index].keyframe = TRUE;
10111             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10112             /* and exit if we have enough samples */
10113             if (G_UNLIKELY (index >= n)) {
10114               i++;
10115               break;
10116             }
10117           }
10118         }
10119         /* save state */
10120         stream->stss_index = i;
10121       }
10122
10123       /* stps marks partial sync frames like open GOP I-Frames */
10124       if (stream->stps_present == TRUE) {
10125         guint32 n_sample_partial_syncs;
10126
10127         n_sample_partial_syncs = stream->n_sample_partial_syncs;
10128
10129         /* if there are no entries, the stss table contains the real
10130          * sync samples */
10131         if (n_sample_partial_syncs) {
10132           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
10133             /* note that the first sample is index 1, not 0 */
10134             guint32 index;
10135
10136             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
10137
10138             if (G_LIKELY (index > 0 && index <= n_samples)) {
10139               index -= 1;
10140               samples[index].keyframe = TRUE;
10141               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
10142               /* and exit if we have enough samples */
10143               if (G_UNLIKELY (index >= n)) {
10144                 i++;
10145                 break;
10146               }
10147             }
10148           }
10149           /* save state */
10150           stream->stps_index = i;
10151         }
10152       }
10153     } else {
10154       /* no stss, all samples are keyframes */
10155       stream->all_keyframe = TRUE;
10156       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
10157     }
10158   }
10159
10160 ctts:
10161   /* composition time to sample */
10162   if (stream->ctts_present == TRUE) {
10163     guint32 n_composition_times;
10164     guint32 ctts_count;
10165     gint32 ctts_soffset;
10166
10167     /* Fill in the pts_offsets */
10168     cur = first;
10169     n_composition_times = stream->n_composition_times;
10170
10171     for (i = stream->ctts_index; i < n_composition_times; i++) {
10172       if (stream->ctts_sample_index >= stream->ctts_count
10173           || !stream->ctts_sample_index) {
10174         stream->ctts_count =
10175             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
10176         stream->ctts_soffset =
10177             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
10178         stream->ctts_sample_index = 0;
10179       }
10180
10181       ctts_count = stream->ctts_count;
10182       ctts_soffset = stream->ctts_soffset;
10183
10184       /* FIXME: Set offset to 0 for "no decode samples". This needs
10185        * to be handled in a codec specific manner ideally. */
10186       if (ctts_soffset == G_MININT32)
10187         ctts_soffset = 0;
10188
10189       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
10190         cur->pts_offset = ctts_soffset;
10191         cur++;
10192
10193         if (G_UNLIKELY (cur > last)) {
10194           /* save state */
10195           stream->ctts_sample_index = j + 1;
10196           goto done;
10197         }
10198       }
10199       stream->ctts_sample_index = 0;
10200       stream->ctts_index++;
10201     }
10202   }
10203 done:
10204   stream->stbl_index = n;
10205   /* if index has been completely parsed, free data that is no-longer needed */
10206   if (n + 1 == stream->n_samples) {
10207     gst_qtdemux_stbl_free (stream);
10208     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
10209     if (qtdemux->pullbased) {
10210       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
10211       while (n + 1 == stream->n_samples)
10212         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
10213           break;
10214     }
10215   }
10216   GST_OBJECT_UNLOCK (qtdemux);
10217
10218   return TRUE;
10219
10220   /* SUCCESS */
10221 already_parsed:
10222   {
10223     GST_LOG_OBJECT (qtdemux,
10224         "Tried to parse up to sample %u but this sample has already been parsed",
10225         n);
10226     /* if fragmented, there may be more */
10227     if (qtdemux->fragmented && n == stream->stbl_index)
10228       goto done;
10229     GST_OBJECT_UNLOCK (qtdemux);
10230     return TRUE;
10231   }
10232   /* ERRORS */
10233 out_of_samples:
10234   {
10235     GST_LOG_OBJECT (qtdemux,
10236         "Tried to parse up to sample %u but there are only %u samples", n + 1,
10237         stream->n_samples);
10238     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10239         (_("This file is corrupt and cannot be played.")), (NULL));
10240     return FALSE;
10241   }
10242 corrupt_file:
10243   {
10244     GST_OBJECT_UNLOCK (qtdemux);
10245     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
10246         (_("This file is corrupt and cannot be played.")), (NULL));
10247     return FALSE;
10248   }
10249 }
10250
10251 /* collect all segment info for @stream.
10252  */
10253 static gboolean
10254 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
10255     GNode * trak)
10256 {
10257   GNode *edts;
10258   /* accept edts if they contain gaps at start and there is only
10259    * one media segment */
10260   gboolean allow_pushbased_edts = TRUE;
10261   gint media_segments_count = 0;
10262
10263   /* parse and prepare segment info from the edit list */
10264   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
10265   stream->n_segments = 0;
10266   stream->segments = NULL;
10267   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
10268     GNode *elst;
10269     gint n_segments;
10270     gint segment_number, entry_size;
10271     guint64 time;
10272     GstClockTime stime;
10273     const guint8 *buffer;
10274     guint8 version;
10275     guint32 size;
10276
10277     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
10278     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
10279       goto done;
10280
10281     buffer = elst->data;
10282
10283     size = QT_UINT32 (buffer);
10284     /* version, flags, n_segments */
10285     if (size < 16) {
10286       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10287       goto done;
10288     }
10289     version = QT_UINT8 (buffer + 8);
10290     entry_size = (version == 1) ? 20 : 12;
10291
10292     n_segments = QT_UINT32 (buffer + 12);
10293
10294     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
10295       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
10296       goto done;
10297     }
10298
10299     /* we might allocate a bit too much, at least allocate 1 segment */
10300     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
10301
10302     /* segments always start from 0 */
10303     time = 0;
10304     stime = 0;
10305     buffer += 16;
10306     for (segment_number = 0; segment_number < n_segments; segment_number++) {
10307       guint64 duration;
10308       guint64 media_time;
10309       gboolean empty_edit = FALSE;
10310       QtDemuxSegment *segment;
10311       guint32 rate_int;
10312       GstClockTime media_start = GST_CLOCK_TIME_NONE;
10313
10314       if (version == 1) {
10315         media_time = QT_UINT64 (buffer + 8);
10316         duration = QT_UINT64 (buffer);
10317         if (media_time == G_MAXUINT64)
10318           empty_edit = TRUE;
10319       } else {
10320         media_time = QT_UINT32 (buffer + 4);
10321         duration = QT_UINT32 (buffer);
10322         if (media_time == G_MAXUINT32)
10323           empty_edit = TRUE;
10324       }
10325
10326       if (!empty_edit)
10327         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
10328
10329       segment = &stream->segments[segment_number];
10330
10331       /* time and duration expressed in global timescale */
10332       segment->time = stime;
10333       if (duration != 0 || empty_edit) {
10334         /* edge case: empty edits with duration=zero are treated here.
10335          * (files should not have these anyway). */
10336
10337         /* add non scaled values so we don't cause roundoff errors */
10338         time += duration;
10339         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10340         segment->duration = stime - segment->time;
10341       } else {
10342         /* zero duration does not imply media_start == media_stop
10343          * but, only specify media_start. The edit ends with the track. */
10344         stime = segment->duration = GST_CLOCK_TIME_NONE;
10345         /* Don't allow more edits after this one. */
10346         n_segments = segment_number + 1;
10347       }
10348       segment->stop_time = stime;
10349
10350       segment->trak_media_start = media_time;
10351       /* media_time expressed in stream timescale */
10352       if (!empty_edit) {
10353         segment->media_start = media_start;
10354         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10355             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10356         media_segments_count++;
10357       } else {
10358         segment->media_start = GST_CLOCK_TIME_NONE;
10359         segment->media_stop = GST_CLOCK_TIME_NONE;
10360       }
10361       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10362
10363       if (rate_int <= 1) {
10364         /* 0 is not allowed, some programs write 1 instead of the floating point
10365          * value */
10366         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10367             rate_int);
10368         segment->rate = 1;
10369       } else {
10370         segment->rate = rate_int / 65536.0;
10371       }
10372
10373       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10374           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10375           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10376           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10377           segment_number, GST_TIME_ARGS (segment->time),
10378           GST_TIME_ARGS (segment->duration),
10379           GST_TIME_ARGS (segment->media_start), media_time,
10380           GST_TIME_ARGS (segment->media_stop),
10381           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10382           stream->timescale);
10383       if (segment->stop_time > qtdemux->segment.stop &&
10384           !qtdemux->upstream_format_is_time) {
10385         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10386             " extends to %" GST_TIME_FORMAT
10387             " past the end of the declared movie duration %" GST_TIME_FORMAT
10388             " movie segment will be extended", segment_number,
10389             GST_TIME_ARGS (segment->stop_time),
10390             GST_TIME_ARGS (qtdemux->segment.stop));
10391         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10392       }
10393
10394       buffer += entry_size;
10395     }
10396     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10397     stream->n_segments = n_segments;
10398     if (media_segments_count != 1)
10399       allow_pushbased_edts = FALSE;
10400   }
10401 done:
10402
10403   /* push based does not handle segments, so act accordingly here,
10404    * and warn if applicable */
10405   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10406     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10407     /* remove and use default one below, we stream like it anyway */
10408     g_free (stream->segments);
10409     stream->segments = NULL;
10410     stream->n_segments = 0;
10411   }
10412
10413   /* no segments, create one to play the complete trak */
10414   if (stream->n_segments == 0) {
10415     GstClockTime stream_duration =
10416         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10417
10418     if (stream->segments == NULL)
10419       stream->segments = g_new (QtDemuxSegment, 1);
10420
10421     /* represent unknown our way */
10422     if (stream_duration == 0)
10423       stream_duration = GST_CLOCK_TIME_NONE;
10424
10425     stream->segments[0].time = 0;
10426     stream->segments[0].stop_time = stream_duration;
10427     stream->segments[0].duration = stream_duration;
10428     stream->segments[0].media_start = 0;
10429     stream->segments[0].media_stop = stream_duration;
10430     stream->segments[0].rate = 1.0;
10431     stream->segments[0].trak_media_start = 0;
10432
10433     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10434         GST_TIME_ARGS (stream_duration));
10435     stream->n_segments = 1;
10436     stream->dummy_segment = TRUE;
10437   }
10438   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10439
10440   return TRUE;
10441 }
10442
10443 /*
10444  * Parses the stsd atom of a svq3 trak looking for
10445  * the SMI and gama atoms.
10446  */
10447 static void
10448 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10449     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10450 {
10451   const guint8 *_gamma = NULL;
10452   GstBuffer *_seqh = NULL;
10453   const guint8 *stsd_data = stsd_entry_data;
10454   guint32 length = QT_UINT32 (stsd_data);
10455   guint16 version;
10456
10457   if (length < 32) {
10458     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10459     goto end;
10460   }
10461
10462   stsd_data += 16;
10463   length -= 16;
10464   version = QT_UINT16 (stsd_data);
10465   if (version == 3) {
10466     if (length >= 70) {
10467       length -= 70;
10468       stsd_data += 70;
10469       while (length > 8) {
10470         guint32 fourcc, size;
10471         const guint8 *data;
10472         size = QT_UINT32 (stsd_data);
10473         fourcc = QT_FOURCC (stsd_data + 4);
10474         data = stsd_data + 8;
10475
10476         if (size == 0) {
10477           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10478               "svq3 atom parsing");
10479           goto end;
10480         }
10481
10482         switch (fourcc) {
10483           case FOURCC_gama:{
10484             if (size == 12) {
10485               _gamma = data;
10486             } else {
10487               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10488                   " for gama atom, expected 12", size);
10489             }
10490             break;
10491           }
10492           case FOURCC_SMI_:{
10493             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10494               guint32 seqh_size;
10495               if (_seqh != NULL) {
10496                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10497                     " found, ignoring");
10498               } else {
10499                 seqh_size = QT_UINT32 (data + 4);
10500                 if (seqh_size > 0) {
10501                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10502                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10503                 }
10504               }
10505             }
10506             break;
10507           }
10508           default:{
10509             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10510                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10511           }
10512         }
10513
10514         if (size <= length) {
10515           length -= size;
10516           stsd_data += size;
10517         }
10518       }
10519     } else {
10520       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10521     }
10522   } else {
10523     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10524         G_GUINT16_FORMAT, version);
10525     goto end;
10526   }
10527
10528 end:
10529   if (gamma) {
10530     *gamma = _gamma;
10531   }
10532   if (seqh) {
10533     *seqh = _seqh;
10534   } else if (_seqh) {
10535     gst_buffer_unref (_seqh);
10536   }
10537 }
10538
10539 static gchar *
10540 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10541 {
10542   GNode *dinf;
10543   GstByteReader dref;
10544   gchar *uri = NULL;
10545
10546   /*
10547    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10548    * atom that might contain a 'data' atom with the rtsp uri.
10549    * This case was reported in bug #597497, some info about
10550    * the hndl atom can be found in TN1195
10551    */
10552   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10553   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10554
10555   if (dinf) {
10556     guint32 dref_num_entries = 0;
10557     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10558         gst_byte_reader_skip (&dref, 4) &&
10559         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10560       gint i;
10561
10562       /* search dref entries for hndl atom */
10563       for (i = 0; i < dref_num_entries; i++) {
10564         guint32 size = 0, type;
10565         guint8 string_len = 0;
10566         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10567             qt_atom_parser_get_fourcc (&dref, &type)) {
10568           if (type == FOURCC_hndl) {
10569             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10570
10571             /* skip data reference handle bytes and the
10572              * following pascal string and some extra 4
10573              * bytes I have no idea what are */
10574             if (!gst_byte_reader_skip (&dref, 4) ||
10575                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10576                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10577               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10578               break;
10579             }
10580
10581             /* iterate over the atoms to find the data atom */
10582             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10583               guint32 atom_size;
10584               guint32 atom_type;
10585
10586               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10587                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10588                 if (atom_type == FOURCC_data) {
10589                   const guint8 *uri_aux = NULL;
10590
10591                   /* found the data atom that might contain the rtsp uri */
10592                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10593                       "hndl atom, interpreting it as an URI");
10594                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10595                           &uri_aux)) {
10596                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10597                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10598                     else
10599                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10600                           "didn't contain a rtsp address");
10601                   } else {
10602                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10603                         "atom contents");
10604                   }
10605                   break;
10606                 }
10607                 /* skipping to the next entry */
10608                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10609                   break;
10610               } else {
10611                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10612                     "atom header");
10613                 break;
10614               }
10615             }
10616             break;
10617           }
10618           /* skip to the next entry */
10619           if (!gst_byte_reader_skip (&dref, size - 8))
10620             break;
10621         } else {
10622           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10623         }
10624       }
10625       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10626     }
10627   }
10628   return uri;
10629 }
10630
10631 #define AMR_NB_ALL_MODES        0x81ff
10632 #define AMR_WB_ALL_MODES        0x83ff
10633 static guint
10634 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10635 {
10636   /* The 'damr' atom is of the form:
10637    *
10638    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10639    *    32 b       8 b          16 b           8 b                 8 b
10640    *
10641    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10642    * represents the highest mode used in the stream (and thus the maximum
10643    * bitrate), with a couple of special cases as seen below.
10644    */
10645
10646   /* Map of frame type ID -> bitrate */
10647   static const guint nb_bitrates[] = {
10648     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10649   };
10650   static const guint wb_bitrates[] = {
10651     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10652   };
10653   GstMapInfo map;
10654   gsize max_mode;
10655   guint16 mode_set;
10656
10657   gst_buffer_map (buf, &map, GST_MAP_READ);
10658
10659   if (map.size != 0x11) {
10660     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10661     goto bad_data;
10662   }
10663
10664   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10665     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10666         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10667     goto bad_data;
10668   }
10669
10670   mode_set = QT_UINT16 (map.data + 13);
10671
10672   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10673     max_mode = 7 + (wb ? 1 : 0);
10674   else
10675     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10676     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10677
10678   if (max_mode == -1) {
10679     GST_DEBUG ("No mode indication was found (mode set) = %x",
10680         (guint) mode_set);
10681     goto bad_data;
10682   }
10683
10684   gst_buffer_unmap (buf, &map);
10685   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10686
10687 bad_data:
10688   gst_buffer_unmap (buf, &map);
10689   return 0;
10690 }
10691
10692 static gboolean
10693 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10694     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10695 {
10696   /*
10697    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10698    * [0 1 2]
10699    * [3 4 5]
10700    * [6 7 8]
10701    */
10702
10703   if (gst_byte_reader_get_remaining (reader) < 36)
10704     return FALSE;
10705
10706   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10707   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10708   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10709   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10710   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10711   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10712   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10713   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10714   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10715
10716   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10717   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10718       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10719       matrix[2] & 0xFF);
10720   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10721       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10722       matrix[5] & 0xFF);
10723   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10724       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10725       matrix[8] & 0xFF);
10726
10727   return TRUE;
10728 }
10729
10730 static void
10731 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10732     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10733 {
10734
10735 /* [a b c]
10736  * [d e f]
10737  * [g h i]
10738  *
10739  * This macro will only compare value abdegh, it expects cfi to have already
10740  * been checked
10741  */
10742 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10743                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10744
10745   /* only handle the cases where the last column has standard values */
10746   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10747     const gchar *rotation_tag = NULL;
10748
10749     /* no rotation needed */
10750     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10751       /* NOP */
10752     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10753       rotation_tag = "rotate-90";
10754     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10755       rotation_tag = "rotate-180";
10756     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10757       rotation_tag = "rotate-270";
10758     } else {
10759       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10760     }
10761
10762     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10763         GST_STR_NULL (rotation_tag));
10764     if (rotation_tag != NULL) {
10765       if (*taglist == NULL)
10766         *taglist = gst_tag_list_new_empty ();
10767       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10768           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10769     }
10770   } else {
10771     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10772   }
10773 }
10774
10775 static gboolean
10776 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10777     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10778 {
10779   GNode *adrm;
10780   guint32 adrm_size;
10781   GstBuffer *adrm_buf = NULL;
10782   QtDemuxAavdEncryptionInfo *info;
10783
10784   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10785   if (G_UNLIKELY (!adrm)) {
10786     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10787     return FALSE;
10788   }
10789   adrm_size = QT_UINT32 (adrm->data);
10790   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10791
10792   stream->protection_scheme_type = FOURCC_aavd;
10793
10794   if (!stream->protection_scheme_info)
10795     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10796
10797   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10798
10799   if (info->default_properties)
10800     gst_structure_free (info->default_properties);
10801   info->default_properties = gst_structure_new ("application/x-aavd",
10802       "encrypted", G_TYPE_BOOLEAN, TRUE,
10803       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10804   gst_buffer_unref (adrm_buf);
10805
10806   *original_fmt = FOURCC_mp4a;
10807   return TRUE;
10808 }
10809
10810 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10811  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10812  * Common Encryption (cenc), the function will also parse the tenc box (defined
10813  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10814  * (typically an enc[v|a|t|s] sample entry); the function will set
10815  * @original_fmt to the fourcc of the original unencrypted stream format.
10816  * Returns TRUE if successful; FALSE otherwise. */
10817 static gboolean
10818 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10819     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10820 {
10821   GNode *sinf;
10822   GNode *frma;
10823   GNode *schm;
10824   GNode *schi;
10825   QtDemuxCencSampleSetInfo *info;
10826   GNode *tenc;
10827   const guint8 *tenc_data;
10828
10829   g_return_val_if_fail (qtdemux != NULL, FALSE);
10830   g_return_val_if_fail (stream != NULL, FALSE);
10831   g_return_val_if_fail (container != NULL, FALSE);
10832   g_return_val_if_fail (original_fmt != NULL, FALSE);
10833
10834   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10835   if (G_UNLIKELY (!sinf)) {
10836     if (stream->protection_scheme_type == FOURCC_cenc
10837         || stream->protection_scheme_type == FOURCC_cbcs) {
10838       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10839           "mandatory for Common Encryption");
10840       return FALSE;
10841     }
10842     return TRUE;
10843   }
10844
10845   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10846   if (G_UNLIKELY (!frma)) {
10847     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10848     return FALSE;
10849   }
10850
10851   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10852   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10853       GST_FOURCC_ARGS (*original_fmt));
10854
10855   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10856   if (!schm) {
10857     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10858     return FALSE;
10859   }
10860   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10861   stream->protection_scheme_version =
10862       QT_UINT32 ((const guint8 *) schm->data + 16);
10863
10864   GST_DEBUG_OBJECT (qtdemux,
10865       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10866       "protection_scheme_version: %#010x",
10867       GST_FOURCC_ARGS (stream->protection_scheme_type),
10868       stream->protection_scheme_version);
10869
10870   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10871   if (!schi) {
10872     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10873     return FALSE;
10874   }
10875   if (stream->protection_scheme_type != FOURCC_cenc &&
10876       stream->protection_scheme_type != FOURCC_piff &&
10877       stream->protection_scheme_type != FOURCC_cbcs) {
10878     GST_ERROR_OBJECT (qtdemux,
10879         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10880         GST_FOURCC_ARGS (stream->protection_scheme_type));
10881     return FALSE;
10882   }
10883
10884   if (G_UNLIKELY (!stream->protection_scheme_info))
10885     stream->protection_scheme_info =
10886         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10887
10888   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10889
10890   if (stream->protection_scheme_type == FOURCC_cenc
10891       || stream->protection_scheme_type == FOURCC_cbcs) {
10892     guint8 is_encrypted;
10893     guint8 iv_size;
10894     guint8 constant_iv_size = 0;
10895     const guint8 *default_kid;
10896     guint8 crypt_byte_block = 0;
10897     guint8 skip_byte_block = 0;
10898     const guint8 *constant_iv = NULL;
10899
10900     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10901     if (!tenc) {
10902       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10903           "which is mandatory for Common Encryption");
10904       return FALSE;
10905     }
10906     tenc_data = (const guint8 *) tenc->data + 12;
10907     is_encrypted = QT_UINT8 (tenc_data + 2);
10908     iv_size = QT_UINT8 (tenc_data + 3);
10909     default_kid = (tenc_data + 4);
10910     if (stream->protection_scheme_type == FOURCC_cbcs) {
10911       guint8 possible_pattern_info;
10912       if (iv_size == 0) {
10913         constant_iv_size = QT_UINT8 (tenc_data + 20);
10914         if (constant_iv_size != 8 && constant_iv_size != 16) {
10915           GST_ERROR_OBJECT (qtdemux,
10916               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10917           return FALSE;
10918         }
10919         constant_iv = (tenc_data + 21);
10920       }
10921       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10922       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10923       skip_byte_block = possible_pattern_info & 0x0f;
10924     }
10925     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10926         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10927         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10928   } else if (stream->protection_scheme_type == FOURCC_piff) {
10929     GstByteReader br;
10930     static const guint8 piff_track_encryption_uuid[] = {
10931       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10932       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10933     };
10934
10935     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10936     if (!tenc) {
10937       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10938           "which is mandatory for Common Encryption");
10939       return FALSE;
10940     }
10941
10942     tenc_data = (const guint8 *) tenc->data + 8;
10943     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10944       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10945       GST_ERROR_OBJECT (qtdemux,
10946           "Unsupported track encryption box with uuid: %s", box_uuid);
10947       g_free (box_uuid);
10948       return FALSE;
10949     }
10950     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10951     gst_byte_reader_init (&br, tenc_data, 20);
10952     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10953       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10954       return FALSE;
10955     }
10956     stream->protection_scheme_type = FOURCC_cenc;
10957   }
10958
10959   return TRUE;
10960 }
10961
10962 static gint
10963 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10964     QtDemuxStream ** stream2)
10965 {
10966   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10967 }
10968
10969 static gboolean
10970 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10971     GNode * stbl)
10972 {
10973   GNode *svmi;
10974
10975   /*parse svmi header if existing */
10976   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10977   if (svmi) {
10978     guint len = QT_UINT32 ((guint8 *) svmi->data);
10979     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10980     if (!version) {
10981       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10982       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10983       guint8 frame_type, frame_layout;
10984       guint32 stereo_mono_change_count;
10985
10986       if (len < 18)
10987         return FALSE;
10988
10989       /* MPEG-A stereo video */
10990       if (qtdemux->major_brand == FOURCC_ss02)
10991         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10992
10993       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10994       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10995       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10996
10997       switch (frame_type) {
10998         case 0:
10999           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
11000           break;
11001         case 1:
11002           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
11003           break;
11004         case 2:
11005           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
11006           break;
11007         case 3:
11008           /* mode 3 is primary/secondary view sequence, ie
11009            * left/right views in separate tracks. See section 7.2
11010            * of ISO/IEC 23000-11:2009 */
11011           /* In the future this might be supported using related
11012            * streams, like an enhancement track - if files like this
11013            * ever exist */
11014           GST_FIXME_OBJECT (qtdemux,
11015               "Implement stereo video in separate streams");
11016       }
11017
11018       if ((frame_layout & 0x1) == 0)
11019         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
11020
11021       GST_LOG_OBJECT (qtdemux,
11022           "StereoVideo: composition type: %u, is_left_first: %u",
11023           frame_type, frame_layout);
11024
11025       if (stereo_mono_change_count > 1) {
11026         GST_FIXME_OBJECT (qtdemux,
11027             "Mixed-mono flags are not yet supported in qtdemux.");
11028       }
11029
11030       stream->multiview_mode = mode;
11031       stream->multiview_flags = flags;
11032     }
11033   }
11034
11035   return TRUE;
11036 }
11037
11038 /* parse the traks.
11039  * With each track we associate a new QtDemuxStream that contains all the info
11040  * about the trak.
11041  * traks that do not decode to something (like strm traks) will not have a pad.
11042  */
11043 static gboolean
11044 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
11045 {
11046   GstByteReader tkhd;
11047   int offset;
11048   GNode *mdia;
11049   GNode *mdhd;
11050   GNode *hdlr;
11051   GNode *minf;
11052   GNode *stbl;
11053   GNode *stsd;
11054   GNode *mp4a;
11055   GNode *mp4v;
11056   GNode *esds;
11057   GNode *tref;
11058   GNode *udta;
11059
11060   QtDemuxStream *stream = NULL;
11061   const guint8 *stsd_data;
11062   const guint8 *stsd_entry_data;
11063   guint remaining_stsd_len;
11064   guint stsd_entry_count;
11065   guint stsd_index;
11066   guint16 lang_code;            /* quicktime lang code or packed iso code */
11067   guint32 version;
11068   guint32 tkhd_flags = 0;
11069   guint8 tkhd_version = 0;
11070   guint32 w = 0, h = 0;
11071   guint value_size, stsd_len, len;
11072   guint32 track_id;
11073   guint32 dummy;
11074
11075   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
11076
11077   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
11078       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
11079       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
11080     goto corrupt_file;
11081
11082   /* pick between 64 or 32 bits */
11083   value_size = tkhd_version == 1 ? 8 : 4;
11084   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
11085       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
11086     goto corrupt_file;
11087
11088   /* Check if current moov has duplicated track_id */
11089   if (qtdemux_find_stream (qtdemux, track_id))
11090     goto existing_stream;
11091
11092   stream = _create_stream (qtdemux, track_id);
11093   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11094
11095   /* need defaults for fragments */
11096   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
11097
11098   if ((tkhd_flags & 1) == 0)
11099     stream->disabled = TRUE;
11100
11101   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
11102       tkhd_version, tkhd_flags, stream->track_id);
11103
11104   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
11105     goto corrupt_file;
11106
11107   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
11108     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
11109     if (qtdemux->major_brand != FOURCC_mjp2 ||
11110         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
11111       goto corrupt_file;
11112   }
11113
11114   len = QT_UINT32 ((guint8 *) mdhd->data);
11115   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
11116   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
11117   if (version == 0x01000000) {
11118     if (len < 42)
11119       goto corrupt_file;
11120     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
11121     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
11122     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
11123   } else {
11124     if (len < 30)
11125       goto corrupt_file;
11126     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
11127     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
11128     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
11129   }
11130
11131   if (lang_code < 0x400) {
11132     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
11133   } else if (lang_code == 0x7fff) {
11134     stream->lang_id[0] = 0;     /* unspecified */
11135   } else {
11136     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
11137     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
11138     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
11139     stream->lang_id[3] = 0;
11140   }
11141
11142   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
11143       stream->timescale);
11144   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
11145       stream->duration);
11146   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
11147       lang_code, stream->lang_id);
11148
11149   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
11150     goto corrupt_file;
11151
11152   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
11153     /* chapters track reference */
11154     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
11155     if (chap) {
11156       gsize length = GST_READ_UINT32_BE (chap->data);
11157       if (qtdemux->chapters_track_id)
11158         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
11159
11160       if (length >= 12) {
11161         qtdemux->chapters_track_id =
11162             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
11163       }
11164     }
11165   }
11166
11167   /* fragmented files may have bogus duration in moov */
11168   if (!qtdemux->fragmented &&
11169       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
11170     guint64 tdur1, tdur2;
11171
11172     /* don't overflow */
11173     tdur1 = stream->timescale * (guint64) qtdemux->duration;
11174     tdur2 = qtdemux->timescale * (guint64) stream->duration;
11175
11176     /* HACK:
11177      * some of those trailers, nowadays, have prologue images that are
11178      * themselves video tracks as well. I haven't really found a way to
11179      * identify those yet, except for just looking at their duration. */
11180     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
11181       GST_WARNING_OBJECT (qtdemux,
11182           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
11183           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
11184           "found, assuming preview image or something; skipping track",
11185           stream->duration, stream->timescale, qtdemux->duration,
11186           qtdemux->timescale);
11187       gst_qtdemux_stream_unref (stream);
11188       return TRUE;
11189     }
11190   }
11191
11192   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
11193     goto corrupt_file;
11194
11195   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
11196       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
11197
11198   len = QT_UINT32 ((guint8 *) hdlr->data);
11199   if (len >= 20)
11200     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
11201   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
11202       GST_FOURCC_ARGS (stream->subtype));
11203
11204   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
11205     goto corrupt_file;
11206
11207   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
11208     goto corrupt_file;
11209
11210   /* Parse out svmi (and later st3d/sv3d) atoms */
11211   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
11212     goto corrupt_file;
11213
11214   /* parse rest of tkhd */
11215   if (stream->subtype == FOURCC_vide) {
11216     guint32 matrix[9];
11217
11218     /* version 1 uses some 64-bit ints */
11219     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
11220       goto corrupt_file;
11221
11222     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
11223       goto corrupt_file;
11224
11225     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
11226         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
11227       goto corrupt_file;
11228
11229     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
11230         &stream->stream_tags);
11231   }
11232
11233   /* parse stsd */
11234   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
11235     goto corrupt_file;
11236   stsd_data = (const guint8 *) stsd->data;
11237
11238   /* stsd should at least have one entry */
11239   stsd_len = QT_UINT32 (stsd_data);
11240   if (stsd_len < 24) {
11241     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
11242     if (stream->subtype == FOURCC_vivo) {
11243       gst_qtdemux_stream_unref (stream);
11244       return TRUE;
11245     } else {
11246       goto corrupt_file;
11247     }
11248   }
11249
11250   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
11251   /* each stsd entry must contain at least 8 bytes */
11252   if (stream->stsd_entries_length == 0
11253       || stream->stsd_entries_length > stsd_len / 8) {
11254     stream->stsd_entries_length = 0;
11255     goto corrupt_file;
11256   }
11257   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
11258   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
11259   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
11260
11261   stsd_entry_data = stsd_data + 16;
11262   remaining_stsd_len = stsd_len - 16;
11263   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
11264     guint32 fourcc;
11265     gchar *codec = NULL;
11266     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
11267
11268     /* and that entry should fit within stsd */
11269     len = QT_UINT32 (stsd_entry_data);
11270     if (len > remaining_stsd_len)
11271       goto corrupt_file;
11272
11273     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
11274     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
11275         GST_FOURCC_ARGS (entry->fourcc));
11276     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
11277
11278     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
11279       goto error_encrypted;
11280
11281     if (fourcc == FOURCC_aavd) {
11282       if (stream->subtype != FOURCC_soun) {
11283         GST_ERROR_OBJECT (qtdemux,
11284             "Unexpeced stsd type 'aavd' outside 'soun' track");
11285       } else {
11286         /* encrypted audio with sound sample description v0 */
11287         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11288         stream->protected = TRUE;
11289         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
11290           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11291       }
11292     }
11293
11294     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
11295       /* FIXME this looks wrong, there might be multiple children
11296        * with the same type */
11297       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
11298       stream->protected = TRUE;
11299       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
11300         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
11301     }
11302
11303     if (stream->subtype == FOURCC_vide) {
11304       GNode *colr;
11305       GNode *fiel;
11306       GNode *pasp;
11307       gboolean gray;
11308       gint depth, palette_size, palette_count;
11309       guint32 *palette_data = NULL;
11310
11311       entry->sampled = TRUE;
11312
11313       stream->display_width = w >> 16;
11314       stream->display_height = h >> 16;
11315
11316       offset = 16;
11317       if (len < 86)             /* TODO verify */
11318         goto corrupt_file;
11319
11320       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
11321       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
11322       entry->fps_n = 0;         /* this is filled in later */
11323       entry->fps_d = 0;         /* this is filled in later */
11324       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
11325       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
11326
11327       /* if color_table_id is 0, ctab atom must follow; however some files
11328        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
11329        * if color table is not present we'll correct the value */
11330       if (entry->color_table_id == 0 &&
11331           (len < 90
11332               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11333         entry->color_table_id = -1;
11334       }
11335
11336       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11337           entry->width, entry->height, entry->bits_per_sample,
11338           entry->color_table_id);
11339
11340       depth = entry->bits_per_sample;
11341
11342       /* more than 32 bits means grayscale */
11343       gray = (depth > 32);
11344       /* low 32 bits specify the depth  */
11345       depth &= 0x1F;
11346
11347       /* different number of palette entries is determined by depth. */
11348       palette_count = 0;
11349       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11350         palette_count = (1 << depth);
11351       palette_size = palette_count * 4;
11352
11353       if (entry->color_table_id) {
11354         switch (palette_count) {
11355           case 0:
11356             break;
11357           case 2:
11358             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11359             break;
11360           case 4:
11361             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11362             break;
11363           case 16:
11364             if (gray)
11365               palette_data =
11366                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11367             else
11368               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11369             break;
11370           case 256:
11371             if (gray)
11372               palette_data =
11373                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11374             else
11375               palette_data =
11376                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11377             break;
11378           default:
11379             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11380                 (_("The video in this file might not play correctly.")),
11381                 ("unsupported palette depth %d", depth));
11382             break;
11383         }
11384       } else {
11385         gint i, j, start, end;
11386
11387         if (len < 94)
11388           goto corrupt_file;
11389
11390         /* read table */
11391         start = QT_UINT32 (stsd_entry_data + offset + 70);
11392         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11393         end = QT_UINT16 (stsd_entry_data + offset + 76);
11394
11395         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11396             start, end, palette_count);
11397
11398         if (end > 255)
11399           end = 255;
11400         if (start > end)
11401           start = end;
11402
11403         if (len < 94 + (end - start) * 8)
11404           goto corrupt_file;
11405
11406         /* palette is always the same size */
11407         palette_data = g_malloc0 (256 * 4);
11408         palette_size = 256 * 4;
11409
11410         for (j = 0, i = start; i <= end; j++, i++) {
11411           guint32 a, r, g, b;
11412
11413           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11414           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11415           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11416           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11417
11418           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11419               (g & 0xff00) | (b >> 8);
11420         }
11421       }
11422
11423       if (entry->caps)
11424         gst_caps_unref (entry->caps);
11425
11426       entry->caps =
11427           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11428           &codec);
11429       if (G_UNLIKELY (!entry->caps)) {
11430         g_free (palette_data);
11431         goto unknown_stream;
11432       }
11433
11434       if (codec) {
11435         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11436             GST_TAG_VIDEO_CODEC, codec, NULL);
11437         g_free (codec);
11438         codec = NULL;
11439       }
11440
11441       if (palette_data) {
11442         GstStructure *s;
11443
11444         if (entry->rgb8_palette)
11445           gst_memory_unref (entry->rgb8_palette);
11446         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11447             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11448
11449         s = gst_caps_get_structure (entry->caps, 0);
11450
11451         /* non-raw video has a palette_data property. raw video has the palette as
11452          * an extra plane that we append to the output buffers before we push
11453          * them*/
11454         if (!gst_structure_has_name (s, "video/x-raw")) {
11455           GstBuffer *palette;
11456
11457           palette = gst_buffer_new ();
11458           gst_buffer_append_memory (palette, entry->rgb8_palette);
11459           entry->rgb8_palette = NULL;
11460
11461           gst_caps_set_simple (entry->caps, "palette_data",
11462               GST_TYPE_BUFFER, palette, NULL);
11463           gst_buffer_unref (palette);
11464         }
11465       } else if (palette_count != 0) {
11466         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11467             (NULL), ("Unsupported palette depth %d", depth));
11468       }
11469
11470       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11471           QT_UINT16 (stsd_entry_data + offset + 32));
11472
11473       esds = NULL;
11474       pasp = NULL;
11475       colr = NULL;
11476       fiel = NULL;
11477       /* pick 'the' stsd child */
11478       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11479       // We should skip parsing the stsd for non-protected streams if
11480       // the entry doesn't match the fourcc, since they don't change
11481       // format. However, for protected streams we can have partial
11482       // encryption, where parts of the stream are encrypted and parts
11483       // not. For both parts of such streams, we should ensure the
11484       // esds overrides are parsed for both from the stsd.
11485       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11486         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11487           mp4v = NULL;
11488         else if (!stream->protected)
11489           mp4v = NULL;
11490       }
11491
11492       if (mp4v) {
11493         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11494         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11495         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11496         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11497       }
11498
11499       if (pasp) {
11500         const guint8 *pasp_data = (const guint8 *) pasp->data;
11501         gint len = QT_UINT32 (pasp_data);
11502
11503         if (len == 16) {
11504           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11505           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11506         } else {
11507           CUR_STREAM (stream)->par_w = 0;
11508           CUR_STREAM (stream)->par_h = 0;
11509         }
11510       } else {
11511         CUR_STREAM (stream)->par_w = 0;
11512         CUR_STREAM (stream)->par_h = 0;
11513       }
11514
11515       if (fiel) {
11516         const guint8 *fiel_data = (const guint8 *) fiel->data;
11517         gint len = QT_UINT32 (fiel_data);
11518
11519         if (len == 10) {
11520           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11521           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11522         }
11523       }
11524
11525       if (colr) {
11526         const guint8 *colr_data = (const guint8 *) colr->data;
11527         gint len = QT_UINT32 (colr_data);
11528
11529         if (len == 19 || len == 18) {
11530           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11531
11532           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11533             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11534             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11535             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11536             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11537
11538             CUR_STREAM (stream)->colorimetry.primaries =
11539                 gst_video_color_primaries_from_iso (primaries);
11540             CUR_STREAM (stream)->colorimetry.transfer =
11541                 gst_video_transfer_function_from_iso (transfer_function);
11542             CUR_STREAM (stream)->colorimetry.matrix =
11543                 gst_video_color_matrix_from_iso (matrix);
11544             CUR_STREAM (stream)->colorimetry.range =
11545                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11546                 GST_VIDEO_COLOR_RANGE_16_235;
11547           } else {
11548             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11549           }
11550         } else {
11551           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11552         }
11553       }
11554
11555       if (esds) {
11556         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11557             stream->stream_tags);
11558       } else {
11559         switch (fourcc) {
11560           case FOURCC_H264:
11561           case FOURCC_avc1:
11562           case FOURCC_avc3:
11563           {
11564             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11565             const guint8 *avc_data = stsd_entry_data + 0x56;
11566
11567             /* find avcC */
11568             while (len >= 0x8) {
11569               gint size;
11570
11571               if (QT_UINT32 (avc_data) <= len)
11572                 size = QT_UINT32 (avc_data) - 0x8;
11573               else
11574                 size = len - 0x8;
11575
11576               if (size < 1)
11577                 /* No real data, so break out */
11578                 break;
11579
11580               switch (QT_FOURCC (avc_data + 0x4)) {
11581                 case FOURCC_avcC:
11582                 {
11583                   /* parse, if found */
11584                   GstBuffer *buf;
11585
11586                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11587
11588                   /* First 4 bytes are the length of the atom, the next 4 bytes
11589                    * are the fourcc, the next 1 byte is the version, and the
11590                    * subsequent bytes are profile_tier_level structure like data. */
11591                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11592                       avc_data + 8 + 1, size - 1);
11593                   buf = gst_buffer_new_and_alloc (size);
11594                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11595                   gst_caps_set_simple (entry->caps,
11596                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11597                   gst_buffer_unref (buf);
11598
11599                   break;
11600                 }
11601                 case FOURCC_strf:
11602                 {
11603                   GstBuffer *buf;
11604
11605                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11606
11607                   /* First 4 bytes are the length of the atom, the next 4 bytes
11608                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11609                    * next 1 byte is the version, and the
11610                    * subsequent bytes are sequence parameter set like data. */
11611
11612                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11613                   if (size > 1) {
11614                     gst_codec_utils_h264_caps_set_level_and_profile
11615                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11616
11617                     buf = gst_buffer_new_and_alloc (size);
11618                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11619                     gst_caps_set_simple (entry->caps,
11620                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11621                     gst_buffer_unref (buf);
11622                   }
11623                   break;
11624                 }
11625                 case FOURCC_btrt:
11626                 {
11627                   guint avg_bitrate, max_bitrate;
11628
11629                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11630                   if (size < 12)
11631                     break;
11632
11633                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11634                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11635
11636                   if (!max_bitrate && !avg_bitrate)
11637                     break;
11638
11639                   /* Some muxers seem to swap the average and maximum bitrates
11640                    * (I'm looking at you, YouTube), so we swap for sanity. */
11641                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11642                     guint temp = avg_bitrate;
11643
11644                     avg_bitrate = max_bitrate;
11645                     max_bitrate = temp;
11646                   }
11647
11648                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11649                     gst_tag_list_add (stream->stream_tags,
11650                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11651                         max_bitrate, NULL);
11652                   }
11653                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11654                     gst_tag_list_add (stream->stream_tags,
11655                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11656                         NULL);
11657                   }
11658
11659                   break;
11660                 }
11661
11662                 default:
11663                   break;
11664               }
11665
11666               len -= size + 8;
11667               avc_data += size + 8;
11668             }
11669
11670             break;
11671           }
11672           case FOURCC_H265:
11673           case FOURCC_hvc1:
11674           case FOURCC_hev1:
11675           case FOURCC_dvh1:
11676           case FOURCC_dvhe:
11677           {
11678             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11679             const guint8 *hevc_data = stsd_entry_data + 0x56;
11680
11681             /* find hevc */
11682             while (len >= 0x8) {
11683               gint size;
11684
11685               if (QT_UINT32 (hevc_data) <= len)
11686                 size = QT_UINT32 (hevc_data) - 0x8;
11687               else
11688                 size = len - 0x8;
11689
11690               if (size < 1)
11691                 /* No real data, so break out */
11692                 break;
11693
11694               switch (QT_FOURCC (hevc_data + 0x4)) {
11695                 case FOURCC_hvcC:
11696                 {
11697                   /* parse, if found */
11698                   GstBuffer *buf;
11699
11700                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11701
11702                   /* First 4 bytes are the length of the atom, the next 4 bytes
11703                    * are the fourcc, the next 1 byte is the version, and the
11704                    * subsequent bytes are sequence parameter set like data. */
11705                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11706                       (entry->caps, hevc_data + 8 + 1, size - 1);
11707
11708                   buf = gst_buffer_new_and_alloc (size);
11709                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11710                   gst_caps_set_simple (entry->caps,
11711                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11712                   gst_buffer_unref (buf);
11713                   break;
11714                 }
11715                 default:
11716                   break;
11717               }
11718               len -= size + 8;
11719               hevc_data += size + 8;
11720             }
11721             break;
11722           }
11723           case FOURCC_mp4v:
11724           case FOURCC_MP4V:
11725           case FOURCC_fmp4:
11726           case FOURCC_FMP4:
11727           case FOURCC_xvid:
11728           case FOURCC_XVID:
11729           {
11730             GNode *glbl;
11731
11732             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11733                 GST_FOURCC_ARGS (fourcc));
11734
11735             /* codec data might be in glbl extension atom */
11736             glbl = mp4v ?
11737                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11738             if (glbl) {
11739               guint8 *data;
11740               GstBuffer *buf;
11741               gint len;
11742
11743               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11744               data = glbl->data;
11745               len = QT_UINT32 (data);
11746               if (len > 0x8) {
11747                 len -= 0x8;
11748                 buf = gst_buffer_new_and_alloc (len);
11749                 gst_buffer_fill (buf, 0, data + 8, len);
11750                 gst_caps_set_simple (entry->caps,
11751                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11752                 gst_buffer_unref (buf);
11753               }
11754             }
11755             break;
11756           }
11757           case FOURCC_mjp2:
11758           {
11759             /* see annex I of the jpeg2000 spec */
11760             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11761             const guint8 *data;
11762             const gchar *colorspace = NULL;
11763             gint ncomp = 0;
11764             guint32 ncomp_map = 0;
11765             gint32 *comp_map = NULL;
11766             guint32 nchan_def = 0;
11767             gint32 *chan_def = NULL;
11768
11769             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11770             /* some required atoms */
11771             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11772             if (!mjp2)
11773               break;
11774             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11775             if (!jp2h)
11776               break;
11777
11778             /* number of components; redundant with info in codestream, but useful
11779                to a muxer */
11780             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11781             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11782               break;
11783             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11784
11785             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11786             if (!colr)
11787               break;
11788             GST_DEBUG_OBJECT (qtdemux, "found colr");
11789             /* extract colour space info */
11790             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11791               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11792                 case 16:
11793                   colorspace = "sRGB";
11794                   break;
11795                 case 17:
11796                   colorspace = "GRAY";
11797                   break;
11798                 case 18:
11799                   colorspace = "sYUV";
11800                   break;
11801                 default:
11802                   colorspace = NULL;
11803                   break;
11804               }
11805             }
11806             if (!colorspace)
11807               /* colr is required, and only values 16, 17, and 18 are specified,
11808                  so error if we have no colorspace */
11809               break;
11810
11811             /* extract component mapping */
11812             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11813             if (cmap) {
11814               guint32 cmap_len = 0;
11815               int i;
11816               cmap_len = QT_UINT32 (cmap->data);
11817               if (cmap_len >= 8) {
11818                 /* normal box, subtract off header */
11819                 cmap_len -= 8;
11820                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11821                 if (cmap_len % 4 == 0) {
11822                   ncomp_map = (cmap_len / 4);
11823                   comp_map = g_new0 (gint32, ncomp_map);
11824                   for (i = 0; i < ncomp_map; i++) {
11825                     guint16 cmp;
11826                     guint8 mtyp, pcol;
11827                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11828                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11829                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11830                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11831                   }
11832                 }
11833               }
11834             }
11835             /* extract channel definitions */
11836             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11837             if (cdef) {
11838               guint32 cdef_len = 0;
11839               int i;
11840               cdef_len = QT_UINT32 (cdef->data);
11841               if (cdef_len >= 10) {
11842                 /* normal box, subtract off header and len */
11843                 cdef_len -= 10;
11844                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11845                 if (cdef_len % 6 == 0) {
11846                   nchan_def = (cdef_len / 6);
11847                   chan_def = g_new0 (gint32, nchan_def);
11848                   for (i = 0; i < nchan_def; i++)
11849                     chan_def[i] = -1;
11850                   for (i = 0; i < nchan_def; i++) {
11851                     guint16 cn, typ, asoc;
11852                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11853                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11854                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11855                     if (cn < nchan_def) {
11856                       switch (typ) {
11857                         case 0:
11858                           chan_def[cn] = asoc;
11859                           break;
11860                         case 1:
11861                           chan_def[cn] = 0;     /* alpha */
11862                           break;
11863                         default:
11864                           chan_def[cn] = -typ;
11865                       }
11866                     }
11867                   }
11868                 }
11869               }
11870             }
11871
11872             gst_caps_set_simple (entry->caps,
11873                 "num-components", G_TYPE_INT, ncomp, NULL);
11874             gst_caps_set_simple (entry->caps,
11875                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11876
11877             if (comp_map) {
11878               GValue arr = { 0, };
11879               GValue elt = { 0, };
11880               int i;
11881               g_value_init (&arr, GST_TYPE_ARRAY);
11882               g_value_init (&elt, G_TYPE_INT);
11883               for (i = 0; i < ncomp_map; i++) {
11884                 g_value_set_int (&elt, comp_map[i]);
11885                 gst_value_array_append_value (&arr, &elt);
11886               }
11887               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11888                   "component-map", &arr);
11889               g_value_unset (&elt);
11890               g_value_unset (&arr);
11891               g_free (comp_map);
11892             }
11893
11894             if (chan_def) {
11895               GValue arr = { 0, };
11896               GValue elt = { 0, };
11897               int i;
11898               g_value_init (&arr, GST_TYPE_ARRAY);
11899               g_value_init (&elt, G_TYPE_INT);
11900               for (i = 0; i < nchan_def; i++) {
11901                 g_value_set_int (&elt, chan_def[i]);
11902                 gst_value_array_append_value (&arr, &elt);
11903               }
11904               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11905                   "channel-definitions", &arr);
11906               g_value_unset (&elt);
11907               g_value_unset (&arr);
11908               g_free (chan_def);
11909             }
11910
11911             /* some optional atoms */
11912             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11913             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11914
11915             /* indicate possible fields in caps */
11916             if (field) {
11917               data = (guint8 *) field->data + 8;
11918               if (*data != 1)
11919                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11920                     (gint) * data, NULL);
11921             }
11922             /* add codec_data if provided */
11923             if (prefix) {
11924               GstBuffer *buf;
11925               gint len;
11926
11927               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11928               data = prefix->data;
11929               len = QT_UINT32 (data);
11930               if (len > 0x8) {
11931                 len -= 0x8;
11932                 buf = gst_buffer_new_and_alloc (len);
11933                 gst_buffer_fill (buf, 0, data + 8, len);
11934                 gst_caps_set_simple (entry->caps,
11935                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11936                 gst_buffer_unref (buf);
11937               }
11938             }
11939             break;
11940           }
11941           case FOURCC_SVQ3:
11942           case FOURCC_VP31:
11943           {
11944             GstBuffer *buf;
11945             GstBuffer *seqh = NULL;
11946             const guint8 *gamma_data = NULL;
11947             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11948
11949             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11950                 &seqh);
11951             if (gamma_data) {
11952               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11953                   QT_FP32 (gamma_data), NULL);
11954             }
11955             if (seqh) {
11956               /* sorry for the bad name, but we don't know what this is, other
11957                * than its own fourcc */
11958               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11959                   NULL);
11960               gst_buffer_unref (seqh);
11961             }
11962
11963             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11964             buf = gst_buffer_new_and_alloc (len);
11965             gst_buffer_fill (buf, 0, stsd_data, len);
11966             gst_caps_set_simple (entry->caps,
11967                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11968             gst_buffer_unref (buf);
11969             break;
11970           }
11971           case FOURCC_jpeg:
11972           {
11973             /* https://developer.apple.com/standards/qtff-2001.pdf,
11974              * page 92, "Video Sample Description", under table 3.1 */
11975             GstByteReader br;
11976
11977             const gint compressor_offset =
11978                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11979             const gint min_size = compressor_offset + 32 + 2 + 2;
11980             GNode *jpeg;
11981             guint32 len;
11982             guint16 color_table_id = 0;
11983             gboolean ok;
11984
11985             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11986
11987             /* recover information on interlaced/progressive */
11988             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11989             if (!jpeg)
11990               break;
11991
11992             len = QT_UINT32 (jpeg->data);
11993             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11994                 min_size);
11995             if (len >= min_size) {
11996               gst_byte_reader_init (&br, jpeg->data, len);
11997
11998               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11999               gst_byte_reader_get_uint16_le (&br, &color_table_id);
12000               if (color_table_id != 0) {
12001                 /* the spec says there can be concatenated chunks in the data, and we want
12002                  * to find one called field. Walk through them. */
12003                 gint offset = min_size;
12004                 while (offset + 8 < len) {
12005                   guint32 size = 0, tag;
12006                   ok = gst_byte_reader_get_uint32_le (&br, &size);
12007                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
12008                   if (!ok || size < 8) {
12009                     GST_WARNING_OBJECT (qtdemux,
12010                         "Failed to walk optional chunk list");
12011                     break;
12012                   }
12013                   GST_DEBUG_OBJECT (qtdemux,
12014                       "Found optional %4.4s chunk, size %u",
12015                       (const char *) &tag, size);
12016                   if (tag == FOURCC_fiel) {
12017                     guint8 n_fields = 0, ordering = 0;
12018                     gst_byte_reader_get_uint8 (&br, &n_fields);
12019                     gst_byte_reader_get_uint8 (&br, &ordering);
12020                     if (n_fields == 1 || n_fields == 2) {
12021                       GST_DEBUG_OBJECT (qtdemux,
12022                           "Found fiel tag with %u fields, ordering %u",
12023                           n_fields, ordering);
12024                       if (n_fields == 2)
12025                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
12026                             "interlace-mode", G_TYPE_STRING, "interleaved",
12027                             NULL);
12028                     } else {
12029                       GST_WARNING_OBJECT (qtdemux,
12030                           "Found fiel tag with invalid fields (%u)", n_fields);
12031                     }
12032                   }
12033                   offset += size;
12034                 }
12035               } else {
12036                 GST_DEBUG_OBJECT (qtdemux,
12037                     "Color table ID is 0, not trying to get interlacedness");
12038               }
12039             } else {
12040               GST_WARNING_OBJECT (qtdemux,
12041                   "Length of jpeg chunk is too small, not trying to get interlacedness");
12042             }
12043
12044             break;
12045           }
12046           case FOURCC_rle_:
12047           case FOURCC_WRLE:
12048           {
12049             gst_caps_set_simple (entry->caps,
12050                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
12051                 NULL);
12052             break;
12053           }
12054           case FOURCC_XiTh:
12055           {
12056             GNode *xith, *xdxt;
12057
12058             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
12059             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12060             if (!xith)
12061               break;
12062
12063             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
12064             if (!xdxt)
12065               break;
12066
12067             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
12068             /* collect the headers and store them in a stream list so that we can
12069              * send them out first */
12070             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
12071             break;
12072           }
12073           case FOURCC_ovc1:
12074           {
12075             GNode *ovc1;
12076             guint8 *ovc1_data;
12077             guint ovc1_len;
12078             GstBuffer *buf;
12079
12080             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
12081             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12082             if (!ovc1)
12083               break;
12084             ovc1_data = ovc1->data;
12085             ovc1_len = QT_UINT32 (ovc1_data);
12086             if (ovc1_len <= 198) {
12087               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
12088               break;
12089             }
12090             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
12091             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
12092             gst_caps_set_simple (entry->caps,
12093                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
12094             gst_buffer_unref (buf);
12095             break;
12096           }
12097           case FOURCC_vc_1:
12098           {
12099             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12100             const guint8 *vc1_data = stsd_entry_data + 0x56;
12101
12102             /* find dvc1 */
12103             while (len >= 8) {
12104               gint size;
12105
12106               if (QT_UINT32 (vc1_data) <= len)
12107                 size = QT_UINT32 (vc1_data) - 8;
12108               else
12109                 size = len - 8;
12110
12111               if (size < 1)
12112                 /* No real data, so break out */
12113                 break;
12114
12115               switch (QT_FOURCC (vc1_data + 0x4)) {
12116                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
12117                 {
12118                   GstBuffer *buf;
12119
12120                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
12121                   buf = gst_buffer_new_and_alloc (size);
12122                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
12123                   gst_caps_set_simple (entry->caps,
12124                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12125                   gst_buffer_unref (buf);
12126                   break;
12127                 }
12128                 default:
12129                   break;
12130               }
12131               len -= size + 8;
12132               vc1_data += size + 8;
12133             }
12134             break;
12135           }
12136           case FOURCC_av01:
12137           {
12138             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12139             const guint8 *av1_data = stsd_entry_data + 0x56;
12140
12141             /* find av1C */
12142             while (len >= 0x8) {
12143               gint size;
12144
12145               if (QT_UINT32 (av1_data) <= len)
12146                 size = QT_UINT32 (av1_data) - 0x8;
12147               else
12148                 size = len - 0x8;
12149
12150               if (size < 1)
12151                 /* No real data, so break out */
12152                 break;
12153
12154               switch (QT_FOURCC (av1_data + 0x4)) {
12155                 case FOURCC_av1C:
12156                 {
12157                   /* parse, if found */
12158                   GstBuffer *buf;
12159                   guint8 pres_delay_field;
12160
12161                   GST_DEBUG_OBJECT (qtdemux,
12162                       "found av1C codec_data in stsd of size %d", size);
12163
12164                   /* not enough data, just ignore and hope for the best */
12165                   if (size < 5)
12166                     break;
12167
12168                   /* Content is:
12169                    * 4 bytes: atom length
12170                    * 4 bytes: fourcc
12171                    * 1 byte: version
12172                    * 3 bytes: flags
12173                    * 3 bits: reserved
12174                    * 1 bits:  initial_presentation_delay_present
12175                    * 4 bits: initial_presentation_delay (if present else reserved
12176                    * rest: OBUs.
12177                    */
12178
12179                   if (av1_data[9] != 0) {
12180                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
12181                     break;
12182                   }
12183
12184                   /* We skip initial_presentation_delay* for now */
12185                   pres_delay_field = *(av1_data + 12);
12186                   if (pres_delay_field & (1 << 5)) {
12187                     gst_caps_set_simple (entry->caps,
12188                         "presentation-delay", G_TYPE_INT,
12189                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
12190                   }
12191                   if (size > 5) {
12192                     buf = gst_buffer_new_and_alloc (size - 5);
12193                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
12194                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
12195                     gst_caps_set_simple (entry->caps,
12196                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
12197                     gst_buffer_unref (buf);
12198                   }
12199                   break;
12200                 }
12201                 default:
12202                   break;
12203               }
12204
12205               len -= size + 8;
12206               av1_data += size + 8;
12207             }
12208
12209             break;
12210           }
12211
12212             /* TODO: Need to parse vpcC for VP8 codec too.
12213              * Note that VPCodecConfigurationBox (vpcC) is defined for
12214              * vp08, vp09, and vp10 fourcc. */
12215           case FOURCC_vp09:
12216           {
12217             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
12218             const guint8 *vpcc_data = stsd_entry_data + 0x56;
12219
12220             /* find vpcC */
12221             while (len >= 0x8) {
12222               gint size;
12223
12224               if (QT_UINT32 (vpcc_data) <= len)
12225                 size = QT_UINT32 (vpcc_data) - 0x8;
12226               else
12227                 size = len - 0x8;
12228
12229               if (size < 1)
12230                 /* No real data, so break out */
12231                 break;
12232
12233               switch (QT_FOURCC (vpcc_data + 0x4)) {
12234                 case FOURCC_vpcC:
12235                 {
12236                   const gchar *profile_str = NULL;
12237                   const gchar *chroma_format_str = NULL;
12238                   guint8 profile;
12239                   guint8 bitdepth;
12240                   guint8 chroma_format;
12241                   GstVideoColorimetry cinfo;
12242
12243                   /* parse, if found */
12244                   GST_DEBUG_OBJECT (qtdemux,
12245                       "found vp codec_data in stsd of size %d", size);
12246
12247                   /* the meaning of "size" is length of the atom body, excluding
12248                    * atom length and fourcc fields */
12249                   if (size < 12)
12250                     break;
12251
12252                   /* Content is:
12253                    * 4 bytes: atom length
12254                    * 4 bytes: fourcc
12255                    * 1 byte: version
12256                    * 3 bytes: flags
12257                    * 1 byte: profile
12258                    * 1 byte: level
12259                    * 4 bits: bitDepth
12260                    * 3 bits: chromaSubsampling
12261                    * 1 bit: videoFullRangeFlag
12262                    * 1 byte: colourPrimaries
12263                    * 1 byte: transferCharacteristics
12264                    * 1 byte: matrixCoefficients
12265                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
12266                    * rest: codecIntializationData (not used for vp8 and vp9)
12267                    */
12268
12269                   if (vpcc_data[8] != 1) {
12270                     GST_WARNING_OBJECT (qtdemux,
12271                         "unknown vpcC version %d", vpcc_data[8]);
12272                     break;
12273                   }
12274
12275                   profile = vpcc_data[12];
12276                   switch (profile) {
12277                     case 0:
12278                       profile_str = "0";
12279                       break;
12280                     case 1:
12281                       profile_str = "1";
12282                       break;
12283                     case 2:
12284                       profile_str = "2";
12285                       break;
12286                     case 3:
12287                       profile_str = "3";
12288                       break;
12289                     default:
12290                       break;
12291                   }
12292
12293                   if (profile_str) {
12294                     gst_caps_set_simple (entry->caps,
12295                         "profile", G_TYPE_STRING, profile_str, NULL);
12296                   }
12297
12298                   /* skip level, the VP9 spec v0.6 defines only one level atm,
12299                    * but webm spec define various ones. Add level to caps
12300                    * if we really need it then */
12301
12302                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
12303                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
12304                     gst_caps_set_simple (entry->caps,
12305                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
12306                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
12307                   }
12308
12309                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
12310                   switch (chroma_format) {
12311                     case 0:
12312                     case 1:
12313                       chroma_format_str = "4:2:0";
12314                       break;
12315                     case 2:
12316                       chroma_format_str = "4:2:2";
12317                       break;
12318                     case 3:
12319                       chroma_format_str = "4:4:4";
12320                       break;
12321                     default:
12322                       break;
12323                   }
12324
12325                   if (chroma_format_str) {
12326                     gst_caps_set_simple (entry->caps,
12327                         "chroma-format", G_TYPE_STRING, chroma_format_str,
12328                         NULL);
12329                   }
12330
12331                   if ((vpcc_data[14] & 0x1) != 0)
12332                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12333                   else
12334                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12335                   cinfo.primaries =
12336                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12337                   cinfo.transfer =
12338                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12339                   cinfo.matrix =
12340                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12341
12342                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12343                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12344                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12345                     /* set this only if all values are known, otherwise this
12346                      * might overwrite valid ones parsed from other color box */
12347                     CUR_STREAM (stream)->colorimetry = cinfo;
12348                   }
12349                   break;
12350                 }
12351                 default:
12352                   break;
12353               }
12354
12355               len -= size + 8;
12356               vpcc_data += size + 8;
12357             }
12358
12359             break;
12360           }
12361           default:
12362             break;
12363         }
12364       }
12365
12366       GST_INFO_OBJECT (qtdemux,
12367           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12368           GST_FOURCC_ARGS (fourcc), entry->caps);
12369
12370     } else if (stream->subtype == FOURCC_soun) {
12371       GNode *wave;
12372       int version, samplesize;
12373       guint16 compression_id;
12374       gboolean amrwb = FALSE;
12375
12376       offset = 16;
12377       /* sample description entry (16) + sound sample description v0 (20) */
12378       if (len < 36)
12379         goto corrupt_file;
12380
12381       version = QT_UINT32 (stsd_entry_data + offset);
12382       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12383       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12384       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12385       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12386
12387       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12388       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12389           QT_UINT32 (stsd_entry_data + offset + 4));
12390       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12391       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12392       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12393       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12394           QT_UINT16 (stsd_entry_data + offset + 14));
12395       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12396
12397       if (compression_id == 0xfffe)
12398         entry->sampled = TRUE;
12399
12400       /* first assume uncompressed audio */
12401       entry->bytes_per_sample = samplesize / 8;
12402       entry->samples_per_frame = entry->n_channels;
12403       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12404       entry->samples_per_packet = entry->samples_per_frame;
12405       entry->bytes_per_packet = entry->bytes_per_sample;
12406
12407       offset = 36;
12408
12409       if (version == 0x00010000) {
12410         /* sample description entry (16) + sound sample description v1 (20+16) */
12411         if (len < 52)
12412           goto corrupt_file;
12413
12414         /* take information from here over the normal sample description */
12415         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12416         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12417         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12418         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12419
12420         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12421         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12422             entry->samples_per_packet);
12423         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12424             entry->bytes_per_packet);
12425         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12426             entry->bytes_per_frame);
12427         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12428             entry->bytes_per_sample);
12429
12430         if (!entry->sampled && entry->bytes_per_packet) {
12431           entry->samples_per_frame = (entry->bytes_per_frame /
12432               entry->bytes_per_packet) * entry->samples_per_packet;
12433           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12434               entry->samples_per_frame);
12435         }
12436       } else if (version == 0x00020000) {
12437         /* sample description entry (16) + sound sample description v2 (56) */
12438         if (len < 72)
12439           goto corrupt_file;
12440
12441         /* take information from here over the normal sample description */
12442         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12443         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12444         entry->samples_per_frame = entry->n_channels;
12445         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12446         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12447         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12448         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12449
12450         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12451         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12452         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12453         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12454             entry->bytes_per_sample * 8);
12455         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12456             QT_UINT32 (stsd_entry_data + offset + 24));
12457         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12458             entry->bytes_per_packet);
12459         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12460             entry->samples_per_packet);
12461       } else if (version != 0x00000) {
12462         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12463             version);
12464       }
12465
12466       switch (fourcc) {
12467           /* Yes, these have to be hard-coded */
12468         case FOURCC_MAC6:
12469         {
12470           entry->samples_per_packet = 6;
12471           entry->bytes_per_packet = 1;
12472           entry->bytes_per_frame = 1 * entry->n_channels;
12473           entry->bytes_per_sample = 1;
12474           entry->samples_per_frame = 6 * entry->n_channels;
12475           break;
12476         }
12477         case FOURCC_MAC3:
12478         {
12479           entry->samples_per_packet = 3;
12480           entry->bytes_per_packet = 1;
12481           entry->bytes_per_frame = 1 * entry->n_channels;
12482           entry->bytes_per_sample = 1;
12483           entry->samples_per_frame = 3 * entry->n_channels;
12484           break;
12485         }
12486         case FOURCC_ima4:
12487         {
12488           entry->samples_per_packet = 64;
12489           entry->bytes_per_packet = 34;
12490           entry->bytes_per_frame = 34 * entry->n_channels;
12491           entry->bytes_per_sample = 2;
12492           entry->samples_per_frame = 64 * entry->n_channels;
12493           break;
12494         }
12495         case FOURCC_ulaw:
12496         case FOURCC_alaw:
12497         {
12498           entry->samples_per_packet = 1;
12499           entry->bytes_per_packet = 1;
12500           entry->bytes_per_frame = 1 * entry->n_channels;
12501           entry->bytes_per_sample = 1;
12502           entry->samples_per_frame = 1 * entry->n_channels;
12503           break;
12504         }
12505         case FOURCC_agsm:
12506         {
12507           entry->samples_per_packet = 160;
12508           entry->bytes_per_packet = 33;
12509           entry->bytes_per_frame = 33 * entry->n_channels;
12510           entry->bytes_per_sample = 2;
12511           entry->samples_per_frame = 160 * entry->n_channels;
12512           break;
12513         }
12514           /* fix up any invalid header information from above */
12515         case FOURCC_twos:
12516         case FOURCC_sowt:
12517         case FOURCC_raw_:
12518         case FOURCC_lpcm:
12519           /* Sometimes these are set to 0 in the sound sample descriptions so
12520            * let's try to infer useful values from the other information we
12521            * have available */
12522           if (entry->bytes_per_sample == 0)
12523             entry->bytes_per_sample =
12524                 entry->bytes_per_frame / entry->n_channels;
12525           if (entry->bytes_per_sample == 0)
12526             entry->bytes_per_sample = samplesize / 8;
12527
12528           if (entry->bytes_per_frame == 0)
12529             entry->bytes_per_frame =
12530                 entry->bytes_per_sample * entry->n_channels;
12531
12532           if (entry->bytes_per_packet == 0)
12533             entry->bytes_per_packet = entry->bytes_per_sample;
12534
12535           if (entry->samples_per_frame == 0)
12536             entry->samples_per_frame = entry->n_channels;
12537
12538           if (entry->samples_per_packet == 0)
12539             entry->samples_per_packet = entry->samples_per_frame;
12540
12541           break;
12542         case FOURCC_in24:
12543         case FOURCC_in32:
12544         case FOURCC_fl32:
12545         case FOURCC_fl64:
12546         case FOURCC_s16l:{
12547           switch (fourcc) {
12548             case FOURCC_in24:
12549               entry->bytes_per_sample = 3;
12550               break;
12551             case FOURCC_in32:
12552             case FOURCC_fl32:
12553               entry->bytes_per_sample = 4;
12554               break;
12555             case FOURCC_fl64:
12556               entry->bytes_per_sample = 8;
12557               break;
12558             case FOURCC_s16l:
12559               entry->bytes_per_sample = 2;
12560               break;
12561             default:
12562               g_assert_not_reached ();
12563               break;
12564           }
12565           entry->samples_per_frame = entry->n_channels;
12566           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12567           entry->samples_per_packet = entry->samples_per_frame;
12568           entry->bytes_per_packet = entry->bytes_per_sample;
12569           break;
12570         }
12571         default:
12572           break;
12573       }
12574
12575       if (entry->caps)
12576         gst_caps_unref (entry->caps);
12577
12578       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12579           stsd_entry_data + 32, len - 16, &codec);
12580
12581       switch (fourcc) {
12582         case FOURCC_in24:
12583         case FOURCC_in32:
12584         case FOURCC_fl32:
12585         case FOURCC_fl64:
12586         {
12587           GNode *enda;
12588           GNode *fmt;
12589
12590           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12591
12592           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12593           if (!enda) {
12594             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12595             if (wave)
12596               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12597           }
12598           if (enda) {
12599             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12600             const gchar *format_str;
12601
12602             switch (fourcc) {
12603               case FOURCC_in24:
12604                 format_str = (enda_value) ? "S24LE" : "S24BE";
12605                 break;
12606               case FOURCC_in32:
12607                 format_str = (enda_value) ? "S32LE" : "S32BE";
12608                 break;
12609               case FOURCC_fl32:
12610                 format_str = (enda_value) ? "F32LE" : "F32BE";
12611                 break;
12612               case FOURCC_fl64:
12613                 format_str = (enda_value) ? "F64LE" : "F64BE";
12614                 break;
12615               default:
12616                 g_assert_not_reached ();
12617                 break;
12618             }
12619             gst_caps_set_simple (entry->caps,
12620                 "format", G_TYPE_STRING, format_str, NULL);
12621           }
12622           break;
12623         }
12624         case FOURCC_owma:
12625         {
12626           const guint8 *owma_data;
12627           const gchar *codec_name = NULL;
12628           guint owma_len;
12629           GstBuffer *buf;
12630           gint version = 1;
12631           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12632           /* FIXME this should also be gst_riff_strf_auds,
12633            * but the latter one is actually missing bits-per-sample :( */
12634           typedef struct
12635           {
12636             gint16 wFormatTag;
12637             gint16 nChannels;
12638             gint32 nSamplesPerSec;
12639             gint32 nAvgBytesPerSec;
12640             gint16 nBlockAlign;
12641             gint16 wBitsPerSample;
12642             gint16 cbSize;
12643           } WAVEFORMATEX;
12644           WAVEFORMATEX *wfex;
12645
12646           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12647           owma_data = stsd_entry_data;
12648           owma_len = QT_UINT32 (owma_data);
12649           if (owma_len <= 54) {
12650             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12651             break;
12652           }
12653           wfex = (WAVEFORMATEX *) (owma_data + 36);
12654           buf = gst_buffer_new_and_alloc (owma_len - 54);
12655           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12656           if (wfex->wFormatTag == 0x0161) {
12657             codec_name = "Windows Media Audio";
12658             version = 2;
12659           } else if (wfex->wFormatTag == 0x0162) {
12660             codec_name = "Windows Media Audio 9 Pro";
12661             version = 3;
12662           } else if (wfex->wFormatTag == 0x0163) {
12663             codec_name = "Windows Media Audio 9 Lossless";
12664             /* is that correct? gstffmpegcodecmap.c is missing it, but
12665              * fluendo codec seems to support it */
12666             version = 4;
12667           }
12668
12669           gst_caps_set_simple (entry->caps,
12670               "codec_data", GST_TYPE_BUFFER, buf,
12671               "wmaversion", G_TYPE_INT, version,
12672               "block_align", G_TYPE_INT,
12673               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12674               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12675               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12676               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12677           gst_buffer_unref (buf);
12678
12679           if (codec_name) {
12680             g_free (codec);
12681             codec = g_strdup (codec_name);
12682           }
12683           break;
12684         }
12685         case FOURCC_wma_:
12686         {
12687           gint len = QT_UINT32 (stsd_entry_data) - offset;
12688           const guint8 *wfex_data = stsd_entry_data + offset;
12689           const gchar *codec_name = NULL;
12690           gint version = 1;
12691           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12692           /* FIXME this should also be gst_riff_strf_auds,
12693            * but the latter one is actually missing bits-per-sample :( */
12694           typedef struct
12695           {
12696             gint16 wFormatTag;
12697             gint16 nChannels;
12698             gint32 nSamplesPerSec;
12699             gint32 nAvgBytesPerSec;
12700             gint16 nBlockAlign;
12701             gint16 wBitsPerSample;
12702             gint16 cbSize;
12703           } WAVEFORMATEX;
12704           WAVEFORMATEX wfex;
12705
12706           /* FIXME: unify with similar wavformatex parsing code above */
12707           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12708
12709           /* find wfex */
12710           while (len >= 8) {
12711             gint size;
12712
12713             if (QT_UINT32 (wfex_data) <= len)
12714               size = QT_UINT32 (wfex_data) - 8;
12715             else
12716               size = len - 8;
12717
12718             if (size < 1)
12719               /* No real data, so break out */
12720               break;
12721
12722             switch (QT_FOURCC (wfex_data + 4)) {
12723               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12724               {
12725                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12726
12727                 if (size < 8 + 18)
12728                   break;
12729
12730                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12731                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12732                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12733                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12734                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12735                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12736                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12737
12738                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12739                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12740                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12741                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12742                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12743                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12744
12745                 if (wfex.wFormatTag == 0x0161) {
12746                   codec_name = "Windows Media Audio";
12747                   version = 2;
12748                 } else if (wfex.wFormatTag == 0x0162) {
12749                   codec_name = "Windows Media Audio 9 Pro";
12750                   version = 3;
12751                 } else if (wfex.wFormatTag == 0x0163) {
12752                   codec_name = "Windows Media Audio 9 Lossless";
12753                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12754                    * fluendo codec seems to support it */
12755                   version = 4;
12756                 }
12757
12758                 gst_caps_set_simple (entry->caps,
12759                     "wmaversion", G_TYPE_INT, version,
12760                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12761                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12762                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12763                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12764
12765                 if (size > wfex.cbSize) {
12766                   GstBuffer *buf;
12767
12768                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12769                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12770                       size - wfex.cbSize);
12771                   gst_caps_set_simple (entry->caps,
12772                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12773                   gst_buffer_unref (buf);
12774                 } else {
12775                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12776                 }
12777
12778                 if (codec_name) {
12779                   g_free (codec);
12780                   codec = g_strdup (codec_name);
12781                 }
12782                 break;
12783               }
12784               default:
12785                 break;
12786             }
12787             len -= size + 8;
12788             wfex_data += size + 8;
12789           }
12790           break;
12791         }
12792         case FOURCC_opus:
12793         {
12794           const guint8 *dops_data;
12795           guint8 *channel_mapping = NULL;
12796           guint32 rate;
12797           guint8 channels;
12798           guint8 channel_mapping_family;
12799           guint8 stream_count;
12800           guint8 coupled_count;
12801           guint8 i;
12802
12803           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12804           if (version == 1)
12805             dops_data = stsd_entry_data + 51;
12806           else
12807             dops_data = stsd_entry_data + 35;
12808
12809           channels = GST_READ_UINT8 (dops_data + 10);
12810           rate = GST_READ_UINT32_LE (dops_data + 13);
12811           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12812           stream_count = GST_READ_UINT8 (dops_data + 20);
12813           coupled_count = GST_READ_UINT8 (dops_data + 21);
12814
12815           if (channels > 0) {
12816             channel_mapping = g_malloc (channels * sizeof (guint8));
12817             for (i = 0; i < channels; i++)
12818               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12819           }
12820
12821           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12822               channel_mapping_family, stream_count, coupled_count,
12823               channel_mapping);
12824           g_free (channel_mapping);
12825           break;
12826         }
12827         default:
12828           break;
12829       }
12830
12831       if (codec) {
12832         GstStructure *s;
12833         gint bitrate = 0;
12834
12835         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12836             GST_TAG_AUDIO_CODEC, codec, NULL);
12837         g_free (codec);
12838         codec = NULL;
12839
12840         /* some bitrate info may have ended up in caps */
12841         s = gst_caps_get_structure (entry->caps, 0);
12842         gst_structure_get_int (s, "bitrate", &bitrate);
12843         if (bitrate > 0)
12844           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12845               GST_TAG_BITRATE, bitrate, NULL);
12846       }
12847
12848       esds = NULL;
12849       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12850       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12851         if (stream->protected) {
12852           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12853             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12854           }
12855           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12856             mp4a = NULL;
12857           }
12858         } else {
12859           mp4a = NULL;
12860         }
12861       }
12862
12863       wave = NULL;
12864       if (mp4a) {
12865         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12866         if (wave)
12867           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12868         if (!esds)
12869           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12870       }
12871
12872
12873       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12874          16 bits is a byte-swapped wave-style codec identifier,
12875          and we can find a WAVE header internally to a 'wave' atom here.
12876          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12877          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12878          is big-endian).
12879        */
12880       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12881         if (len < offset + 20) {
12882           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12883         } else {
12884           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12885           const guint8 *data = stsd_entry_data + offset + 16;
12886           GNode *wavenode;
12887           GNode *waveheadernode;
12888
12889           wavenode = g_node_new ((guint8 *) data);
12890           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12891             const guint8 *waveheader;
12892             guint32 headerlen;
12893
12894             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12895             if (waveheadernode) {
12896               waveheader = (const guint8 *) waveheadernode->data;
12897               headerlen = QT_UINT32 (waveheader);
12898
12899               if (headerlen > 8) {
12900                 gst_riff_strf_auds *header = NULL;
12901                 GstBuffer *headerbuf;
12902                 GstBuffer *extra;
12903
12904                 waveheader += 8;
12905                 headerlen -= 8;
12906
12907                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12908                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12909
12910                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12911                         headerbuf, &header, &extra)) {
12912                   gst_caps_unref (entry->caps);
12913                   /* FIXME: Need to do something with the channel reorder map */
12914                   entry->caps =
12915                       gst_riff_create_audio_caps (header->format, NULL, header,
12916                       extra, NULL, NULL, NULL);
12917
12918                   if (extra)
12919                     gst_buffer_unref (extra);
12920                   g_free (header);
12921                 }
12922               }
12923             } else
12924               GST_DEBUG ("Didn't find waveheadernode for this codec");
12925           }
12926           g_node_destroy (wavenode);
12927         }
12928       } else if (esds) {
12929         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12930             stream->stream_tags);
12931       } else {
12932         switch (fourcc) {
12933 #if 0
12934             /* FIXME: what is in the chunk? */
12935           case FOURCC_QDMC:
12936           {
12937             gint len = QT_UINT32 (stsd_data);
12938
12939             /* seems to be always = 116 = 0x74 */
12940             break;
12941           }
12942 #endif
12943           case FOURCC_QDM2:
12944           {
12945             gint len = QT_UINT32 (stsd_entry_data);
12946
12947             if (len > 0x3C) {
12948               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12949
12950               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12951               gst_caps_set_simple (entry->caps,
12952                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12953               gst_buffer_unref (buf);
12954             }
12955             gst_caps_set_simple (entry->caps,
12956                 "samplesize", G_TYPE_INT, samplesize, NULL);
12957             break;
12958           }
12959           case FOURCC_alac:
12960           {
12961             GNode *alac, *wave = NULL;
12962
12963             /* apparently, m4a has this atom appended directly in the stsd entry,
12964              * while mov has it in a wave atom */
12965             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12966             if (alac) {
12967               /* alac now refers to stsd entry atom */
12968               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12969               if (wave)
12970                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12971               else
12972                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12973             }
12974             if (alac) {
12975               const guint8 *alac_data = alac->data;
12976               gint len = QT_UINT32 (alac->data);
12977               GstBuffer *buf;
12978
12979               if (len < 36) {
12980                 GST_DEBUG_OBJECT (qtdemux,
12981                     "discarding alac atom with unexpected len %d", len);
12982               } else {
12983                 /* codec-data contains alac atom size and prefix,
12984                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12985                 buf = gst_buffer_new_and_alloc (len);
12986                 gst_buffer_fill (buf, 0, alac->data, len);
12987                 gst_caps_set_simple (entry->caps,
12988                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12989                 gst_buffer_unref (buf);
12990
12991                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12992                 entry->n_channels = QT_UINT8 (alac_data + 21);
12993                 entry->rate = QT_UINT32 (alac_data + 32);
12994                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12995               }
12996             }
12997             gst_caps_set_simple (entry->caps,
12998                 "samplesize", G_TYPE_INT, samplesize, NULL);
12999             break;
13000           }
13001           case FOURCC_fLaC:
13002           {
13003             /* The codingname of the sample entry is 'fLaC' */
13004             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
13005
13006             if (flac) {
13007               /* The 'dfLa' box is added to the sample entry to convey
13008                  initializing information for the decoder. */
13009               const GNode *dfla =
13010                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
13011
13012               if (dfla) {
13013                 const guint32 len = QT_UINT32 (dfla->data);
13014
13015                 /* Must contain at least dfLa box header (12),
13016                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
13017                 if (len < 50) {
13018                   GST_DEBUG_OBJECT (qtdemux,
13019                       "discarding dfla atom with unexpected len %d", len);
13020                 } else {
13021                   /* skip dfLa header to get the METADATA_BLOCKs */
13022                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
13023                   const guint32 metadata_blocks_len = len - 12;
13024
13025                   gchar *stream_marker = g_strdup ("fLaC");
13026                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
13027                       strlen (stream_marker));
13028
13029                   guint32 index = 0;
13030                   guint32 remainder = 0;
13031                   guint32 block_size = 0;
13032                   gboolean is_last = FALSE;
13033
13034                   GValue array = G_VALUE_INIT;
13035                   GValue value = G_VALUE_INIT;
13036
13037                   g_value_init (&array, GST_TYPE_ARRAY);
13038                   g_value_init (&value, GST_TYPE_BUFFER);
13039
13040                   gst_value_set_buffer (&value, block);
13041                   gst_value_array_append_value (&array, &value);
13042                   g_value_reset (&value);
13043
13044                   gst_buffer_unref (block);
13045
13046                   /* check there's at least one METADATA_BLOCK_HEADER's worth
13047                    * of data, and we haven't already finished parsing */
13048                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
13049                     remainder = metadata_blocks_len - index;
13050
13051                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
13052                     block_size = 4 +
13053                         (metadata_blocks[index + 1] << 16) +
13054                         (metadata_blocks[index + 2] << 8) +
13055                         metadata_blocks[index + 3];
13056
13057                     /* be careful not to read off end of box */
13058                     if (block_size > remainder) {
13059                       break;
13060                     }
13061
13062                     is_last = metadata_blocks[index] >> 7;
13063
13064                     block = gst_buffer_new_and_alloc (block_size);
13065
13066                     gst_buffer_fill (block, 0, &metadata_blocks[index],
13067                         block_size);
13068
13069                     gst_value_set_buffer (&value, block);
13070                     gst_value_array_append_value (&array, &value);
13071                     g_value_reset (&value);
13072
13073                     gst_buffer_unref (block);
13074
13075                     index += block_size;
13076                   }
13077
13078                   /* only append the metadata if we successfully read all of it */
13079                   if (is_last) {
13080                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
13081                             (stream)->caps, 0), "streamheader", &array);
13082                   } else {
13083                     GST_WARNING_OBJECT (qtdemux,
13084                         "discarding all METADATA_BLOCKs due to invalid "
13085                         "block_size %d at idx %d, rem %d", block_size, index,
13086                         remainder);
13087                   }
13088
13089                   g_value_unset (&value);
13090                   g_value_unset (&array);
13091
13092                   /* The sample rate obtained from the stsd may not be accurate
13093                    * since it cannot represent rates greater than 65535Hz, so
13094                    * override that value with the sample rate from the
13095                    * METADATA_BLOCK_STREAMINFO block */
13096                   CUR_STREAM (stream)->rate =
13097                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
13098                 }
13099               }
13100             }
13101             break;
13102           }
13103           case FOURCC_sawb:
13104             /* Fallthrough! */
13105             amrwb = TRUE;
13106           case FOURCC_samr:
13107           {
13108             gint len = QT_UINT32 (stsd_entry_data);
13109
13110             if (len > 0x24) {
13111               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
13112               guint bitrate;
13113
13114               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
13115
13116               /* If we have enough data, let's try to get the 'damr' atom. See
13117                * the 3GPP container spec (26.244) for more details. */
13118               if ((len - 0x34) > 8 &&
13119                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
13120                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13121                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
13122               }
13123
13124               gst_caps_set_simple (entry->caps,
13125                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13126               gst_buffer_unref (buf);
13127             }
13128             break;
13129           }
13130           case FOURCC_mp4a:
13131           {
13132             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
13133             gint len = QT_UINT32 (stsd_entry_data);
13134             guint16 sound_version = 0;
13135             /* FIXME: Can this be determined somehow? There doesn't seem to be
13136              * anything in mp4a atom that specifis compression */
13137             gint profile = 2;
13138             guint16 channels = entry->n_channels;
13139             guint32 time_scale = (guint32) entry->rate;
13140             gint sample_rate_index = -1;
13141
13142             if (len >= 34) {
13143               sound_version = QT_UINT16 (stsd_entry_data + 16);
13144
13145               if (sound_version == 1) {
13146                 channels = QT_UINT16 (stsd_entry_data + 24);
13147                 time_scale = QT_UINT32 (stsd_entry_data + 30);
13148               } else {
13149                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
13150                     sound_version);
13151               }
13152             } else {
13153               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
13154                   len);
13155             }
13156
13157             sample_rate_index =
13158                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
13159             if (sample_rate_index >= 0 && channels > 0) {
13160               guint8 codec_data[2];
13161               GstBuffer *buf;
13162
13163               /* build AAC codec data */
13164               codec_data[0] = profile << 3;
13165               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
13166               codec_data[1] = (sample_rate_index & 0x01) << 7;
13167               codec_data[1] |= (channels & 0xF) << 3;
13168
13169               buf = gst_buffer_new_and_alloc (2);
13170               gst_buffer_fill (buf, 0, codec_data, 2);
13171               gst_caps_set_simple (entry->caps,
13172                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
13173               gst_buffer_unref (buf);
13174             }
13175             break;
13176           }
13177           case FOURCC_lpcm:
13178           case FOURCC_in24:
13179           case FOURCC_in32:
13180           case FOURCC_fl32:
13181           case FOURCC_fl64:
13182           case FOURCC_s16l:
13183             /* Fully handled elsewhere */
13184             break;
13185           default:
13186             GST_INFO_OBJECT (qtdemux,
13187                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13188             break;
13189         }
13190       }
13191       GST_INFO_OBJECT (qtdemux,
13192           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13193           GST_FOURCC_ARGS (fourcc), entry->caps);
13194
13195     } else if (stream->subtype == FOURCC_strm) {
13196       if (fourcc == FOURCC_rtsp) {
13197         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
13198       } else {
13199         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
13200             GST_FOURCC_ARGS (fourcc));
13201         goto unknown_stream;
13202       }
13203       entry->sampled = TRUE;
13204     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
13205         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
13206         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
13207
13208       entry->sampled = TRUE;
13209       entry->sparse = TRUE;
13210
13211       entry->caps =
13212           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13213           &codec);
13214       if (codec) {
13215         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13216             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13217         g_free (codec);
13218         codec = NULL;
13219       }
13220
13221       /* hunt for sort-of codec data */
13222       switch (fourcc) {
13223         case FOURCC_mp4s:
13224         {
13225           GNode *mp4s = NULL;
13226           GNode *esds = NULL;
13227
13228           /* look for palette in a stsd->mp4s->esds sub-atom */
13229           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
13230           if (mp4s)
13231             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
13232           if (esds == NULL) {
13233             /* Invalid STSD */
13234             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
13235             break;
13236           }
13237
13238           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
13239               stream->stream_tags);
13240           break;
13241         }
13242         default:
13243           GST_INFO_OBJECT (qtdemux,
13244               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13245           break;
13246       }
13247       GST_INFO_OBJECT (qtdemux,
13248           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13249           GST_FOURCC_ARGS (fourcc), entry->caps);
13250     } else if (stream->subtype == FOURCC_meta) {
13251       entry->sampled = TRUE;
13252       entry->sparse = TRUE;
13253
13254       entry->caps =
13255           qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13256           &codec);
13257       if (codec) {
13258         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13259             GST_TAG_CODEC, codec, NULL);
13260         g_free (codec);
13261         codec = NULL;
13262       }
13263
13264       GST_INFO_OBJECT (qtdemux,
13265           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
13266           GST_FOURCC_ARGS (fourcc), entry->caps);
13267     } else {
13268       /* everything in 1 sample */
13269       entry->sampled = TRUE;
13270
13271       entry->caps =
13272           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
13273           &codec);
13274
13275       if (entry->caps == NULL)
13276         goto unknown_stream;
13277
13278       if (codec) {
13279         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13280             GST_TAG_SUBTITLE_CODEC, codec, NULL);
13281         g_free (codec);
13282         codec = NULL;
13283       }
13284     }
13285
13286     /* promote to sampled format */
13287     if (entry->fourcc == FOURCC_samr) {
13288       /* force mono 8000 Hz for AMR */
13289       entry->sampled = TRUE;
13290       entry->n_channels = 1;
13291       entry->rate = 8000;
13292     } else if (entry->fourcc == FOURCC_sawb) {
13293       /* force mono 16000 Hz for AMR-WB */
13294       entry->sampled = TRUE;
13295       entry->n_channels = 1;
13296       entry->rate = 16000;
13297     } else if (entry->fourcc == FOURCC_mp4a) {
13298       entry->sampled = TRUE;
13299     }
13300
13301
13302     stsd_entry_data += len;
13303     remaining_stsd_len -= len;
13304
13305   }
13306
13307   /* collect sample information */
13308   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
13309     goto samples_failed;
13310
13311   if (qtdemux->fragmented) {
13312     guint64 offset;
13313
13314     /* need all moov samples as basis; probably not many if any at all */
13315     /* prevent moof parsing taking of at this time */
13316     offset = qtdemux->moof_offset;
13317     qtdemux->moof_offset = 0;
13318     if (stream->n_samples &&
13319         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
13320       qtdemux->moof_offset = offset;
13321       goto samples_failed;
13322     }
13323     qtdemux->moof_offset = offset;
13324     /* movie duration more reliable in this case (e.g. mehd) */
13325     if (qtdemux->segment.duration &&
13326         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
13327       stream->duration =
13328           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
13329   }
13330
13331   /* configure segments */
13332   if (!qtdemux_parse_segments (qtdemux, stream, trak))
13333     goto segments_failed;
13334
13335   /* add some language tag, if useful */
13336   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
13337       strcmp (stream->lang_id, "und")) {
13338     const gchar *lang_code;
13339
13340     /* convert ISO 639-2 code to ISO 639-1 */
13341     lang_code = gst_tag_get_language_code (stream->lang_id);
13342     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13343         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
13344   }
13345
13346   /* Check for UDTA tags */
13347   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
13348     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13349   }
13350
13351   /* Insert and sort new stream in track-id order.
13352    * This will help in comparing old/new streams during stream update check */
13353   g_ptr_array_add (qtdemux->active_streams, stream);
13354   g_ptr_array_sort (qtdemux->active_streams,
13355       (GCompareFunc) qtdemux_track_id_compare_func);
13356   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13357       QTDEMUX_N_STREAMS (qtdemux));
13358
13359   return TRUE;
13360
13361 /* ERRORS */
13362 corrupt_file:
13363   {
13364     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13365         (_("This file is corrupt and cannot be played.")), (NULL));
13366     if (stream)
13367       gst_qtdemux_stream_unref (stream);
13368     return FALSE;
13369   }
13370 error_encrypted:
13371   {
13372     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13373     gst_qtdemux_stream_unref (stream);
13374     return FALSE;
13375   }
13376 samples_failed:
13377 segments_failed:
13378   {
13379     /* we posted an error already */
13380     /* free stbl sub-atoms */
13381     gst_qtdemux_stbl_free (stream);
13382     gst_qtdemux_stream_unref (stream);
13383     return FALSE;
13384   }
13385 existing_stream:
13386   {
13387     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13388         track_id);
13389     return TRUE;
13390   }
13391 unknown_stream:
13392   {
13393     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13394         GST_FOURCC_ARGS (stream->subtype));
13395     gst_qtdemux_stream_unref (stream);
13396     return TRUE;
13397   }
13398 }
13399
13400 /* If we can estimate the overall bitrate, and don't have information about the
13401  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13402  * the overall bitrate minus the sum of the bitrates of all other streams. This
13403  * should be useful for the common case where we have one audio and one video
13404  * stream and can estimate the bitrate of one, but not the other. */
13405 static void
13406 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13407 {
13408   QtDemuxStream *stream = NULL;
13409   gint64 size, sys_bitrate, sum_bitrate = 0;
13410   GstClockTime duration;
13411   guint bitrate;
13412   gint i;
13413
13414   if (qtdemux->fragmented)
13415     return;
13416
13417   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13418
13419   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13420       || size <= 0) {
13421     GST_DEBUG_OBJECT (qtdemux,
13422         "Size in bytes of the stream not known - bailing");
13423     return;
13424   }
13425
13426   /* Subtract the header size */
13427   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13428       size, qtdemux->header_size);
13429
13430   if (size < qtdemux->header_size)
13431     return;
13432
13433   size = size - qtdemux->header_size;
13434
13435   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13436     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13437     return;
13438   }
13439
13440   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13441     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13442     switch (str->subtype) {
13443       case FOURCC_soun:
13444       case FOURCC_vide:
13445         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13446             CUR_STREAM (str)->caps);
13447         /* retrieve bitrate, prefer avg then max */
13448         bitrate = 0;
13449         if (str->stream_tags) {
13450           if (gst_tag_list_get_uint (str->stream_tags,
13451                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13452             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13453           if (gst_tag_list_get_uint (str->stream_tags,
13454                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13455             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13456           if (gst_tag_list_get_uint (str->stream_tags,
13457                   GST_TAG_BITRATE, &bitrate))
13458             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13459         }
13460         if (bitrate)
13461           sum_bitrate += bitrate;
13462         else {
13463           if (stream) {
13464             GST_DEBUG_OBJECT (qtdemux,
13465                 ">1 stream with unknown bitrate - bailing");
13466             return;
13467           } else
13468             stream = str;
13469         }
13470
13471       default:
13472         /* For other subtypes, we assume no significant impact on bitrate */
13473         break;
13474     }
13475   }
13476
13477   if (!stream) {
13478     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13479     return;
13480   }
13481
13482   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13483
13484   if (sys_bitrate < sum_bitrate) {
13485     /* This can happen, since sum_bitrate might be derived from maximum
13486      * bitrates and not average bitrates */
13487     GST_DEBUG_OBJECT (qtdemux,
13488         "System bitrate less than sum bitrate - bailing");
13489     return;
13490   }
13491
13492   bitrate = sys_bitrate - sum_bitrate;
13493   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13494       ", Stream bitrate = %u", sys_bitrate, bitrate);
13495
13496   if (!stream->stream_tags)
13497     stream->stream_tags = gst_tag_list_new_empty ();
13498   else
13499     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13500
13501   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13502       GST_TAG_BITRATE, bitrate, NULL);
13503 }
13504
13505 static GstFlowReturn
13506 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13507 {
13508   GstFlowReturn ret = GST_FLOW_OK;
13509   gint i;
13510
13511   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13512
13513   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13514     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13515     guint32 sample_num = 0;
13516
13517     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13518         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13519
13520     if (qtdemux->fragmented && qtdemux->pullbased) {
13521       /* need all moov samples first */
13522       GST_OBJECT_LOCK (qtdemux);
13523       while (stream->n_samples == 0)
13524         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13525           break;
13526       GST_OBJECT_UNLOCK (qtdemux);
13527     } else {
13528       /* discard any stray moof */
13529       qtdemux->moof_offset = 0;
13530     }
13531
13532     /* prepare braking */
13533     if (ret != GST_FLOW_ERROR)
13534       ret = GST_FLOW_OK;
13535
13536     /* in pull mode, we should have parsed some sample info by now;
13537      * and quite some code will not handle no samples.
13538      * in push mode, we'll just have to deal with it */
13539     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13540       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13541       g_ptr_array_remove_index (qtdemux->active_streams, i);
13542       i--;
13543       continue;
13544     } else if (stream->track_id == qtdemux->chapters_track_id &&
13545         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13546       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13547          so that it doesn't look like a subtitle track */
13548       g_ptr_array_remove_index (qtdemux->active_streams, i);
13549       i--;
13550       continue;
13551     }
13552
13553     /* parse the initial sample for use in setting the frame rate cap */
13554     while (sample_num == 0 && sample_num < stream->n_samples) {
13555       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13556         break;
13557       ++sample_num;
13558     }
13559   }
13560
13561   return ret;
13562 }
13563
13564 static gboolean
13565 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13566 {
13567   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13568 }
13569
13570 static gboolean
13571 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13572 {
13573   gint i;
13574
13575   /* Different length, updated */
13576   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13577     return TRUE;
13578
13579   /* streams in list are sorted in track-id order */
13580   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13581     /* Different stream-id, updated */
13582     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13583             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13584       return TRUE;
13585   }
13586
13587   return FALSE;
13588 }
13589
13590 static gboolean
13591 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13592     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13593 {
13594   /* Connect old stream's srcpad to new stream */
13595   newstream->pad = oldstream->pad;
13596   oldstream->pad = NULL;
13597
13598   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13599    * case we need to force one through */
13600   newstream->new_stream = newstream->pad != NULL
13601       && GST_PAD_IS_EOS (newstream->pad);
13602
13603   return gst_qtdemux_configure_stream (qtdemux, newstream);
13604 }
13605
13606 static gboolean
13607 qtdemux_update_streams (GstQTDemux * qtdemux)
13608 {
13609   gint i;
13610   g_assert (qtdemux->streams_aware);
13611
13612   /* At below, figure out which stream in active_streams has identical stream-id
13613    * with that of in old_streams. If there is matching stream-id,
13614    * corresponding newstream will not be exposed again,
13615    * but demux will reuse srcpad of matched old stream
13616    *
13617    * active_streams : newly created streams from the latest moov
13618    * old_streams : existing streams (belong to previous moov)
13619    */
13620
13621   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13622     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13623     QtDemuxStream *oldstream = NULL;
13624     guint target;
13625
13626     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13627         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13628
13629     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13630             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13631       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13632
13633       /* null pad stream cannot be reused */
13634       if (oldstream->pad == NULL)
13635         oldstream = NULL;
13636     }
13637
13638     if (oldstream) {
13639       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13640
13641       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13642         return FALSE;
13643
13644       /* we don't need to preserve order of old streams */
13645       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13646     } else {
13647       GstTagList *list;
13648
13649       /* now we have all info and can expose */
13650       list = stream->stream_tags;
13651       stream->stream_tags = NULL;
13652       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13653         return FALSE;
13654     }
13655   }
13656
13657   return TRUE;
13658 }
13659
13660 /* Must be called with expose lock */
13661 static GstFlowReturn
13662 qtdemux_expose_streams (GstQTDemux * qtdemux)
13663 {
13664   gint i;
13665
13666   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13667
13668   if (!qtdemux_is_streams_update (qtdemux)) {
13669     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13670     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13671       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13672       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13673       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13674         return GST_FLOW_ERROR;
13675     }
13676
13677     g_ptr_array_set_size (qtdemux->old_streams, 0);
13678     qtdemux->need_segment = TRUE;
13679
13680     return GST_FLOW_OK;
13681   }
13682
13683   if (qtdemux->streams_aware) {
13684     if (!qtdemux_update_streams (qtdemux))
13685       return GST_FLOW_ERROR;
13686   } else {
13687     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13688       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13689       GstTagList *list;
13690
13691       /* now we have all info and can expose */
13692       list = stream->stream_tags;
13693       stream->stream_tags = NULL;
13694       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13695         return GST_FLOW_ERROR;
13696
13697     }
13698   }
13699
13700   gst_qtdemux_guess_bitrate (qtdemux);
13701
13702   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13703
13704   /* If we have still old_streams, it's no more used stream */
13705   for (i = 0; i < qtdemux->old_streams->len; i++) {
13706     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13707
13708     if (stream->pad) {
13709       GstEvent *event;
13710
13711       event = gst_event_new_eos ();
13712       if (qtdemux->segment_seqnum)
13713         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13714
13715       gst_pad_push_event (stream->pad, event);
13716     }
13717   }
13718
13719   g_ptr_array_set_size (qtdemux->old_streams, 0);
13720
13721   /* check if we should post a redirect in case there is a single trak
13722    * and it is a redirecting trak */
13723   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13724       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13725     GstMessage *m;
13726
13727     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13728         "an external content");
13729     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13730         gst_structure_new ("redirect",
13731             "new-location", G_TYPE_STRING,
13732             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13733     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13734     g_free (qtdemux->redirect_location);
13735     qtdemux->redirect_location =
13736         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13737   }
13738
13739   g_ptr_array_foreach (qtdemux->active_streams,
13740       (GFunc) qtdemux_do_allocation, qtdemux);
13741
13742   qtdemux->need_segment = TRUE;
13743
13744   qtdemux->exposed = TRUE;
13745   return GST_FLOW_OK;
13746 }
13747
13748 typedef struct
13749 {
13750   GstStructure *structure;      /* helper for sort function */
13751   gchar *location;
13752   guint min_req_bitrate;
13753   guint min_req_qt_version;
13754 } GstQtReference;
13755
13756 static gint
13757 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13758 {
13759   GstQtReference *ref_a = (GstQtReference *) a;
13760   GstQtReference *ref_b = (GstQtReference *) b;
13761
13762   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13763     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13764
13765   /* known bitrates go before unknown; higher bitrates go first */
13766   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13767 }
13768
13769 /* sort the redirects and post a message for the application.
13770  */
13771 static void
13772 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13773 {
13774   GstQtReference *best;
13775   GstStructure *s;
13776   GstMessage *msg;
13777   GValue list_val = { 0, };
13778   GList *l;
13779
13780   g_assert (references != NULL);
13781
13782   references = g_list_sort (references, qtdemux_redirects_sort_func);
13783
13784   best = (GstQtReference *) references->data;
13785
13786   g_value_init (&list_val, GST_TYPE_LIST);
13787
13788   for (l = references; l != NULL; l = l->next) {
13789     GstQtReference *ref = (GstQtReference *) l->data;
13790     GValue struct_val = { 0, };
13791
13792     ref->structure = gst_structure_new ("redirect",
13793         "new-location", G_TYPE_STRING, ref->location, NULL);
13794
13795     if (ref->min_req_bitrate > 0) {
13796       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13797           ref->min_req_bitrate, NULL);
13798     }
13799
13800     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13801     g_value_set_boxed (&struct_val, ref->structure);
13802     gst_value_list_append_value (&list_val, &struct_val);
13803     g_value_unset (&struct_val);
13804     /* don't free anything here yet, since we need best->structure below */
13805   }
13806
13807   g_assert (best != NULL);
13808   s = gst_structure_copy (best->structure);
13809
13810   if (g_list_length (references) > 1) {
13811     gst_structure_set_value (s, "locations", &list_val);
13812   }
13813
13814   g_value_unset (&list_val);
13815
13816   for (l = references; l != NULL; l = l->next) {
13817     GstQtReference *ref = (GstQtReference *) l->data;
13818
13819     gst_structure_free (ref->structure);
13820     g_free (ref->location);
13821     g_free (ref);
13822   }
13823   g_list_free (references);
13824
13825   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13826   g_free (qtdemux->redirect_location);
13827   qtdemux->redirect_location =
13828       g_strdup (gst_structure_get_string (s, "new-location"));
13829   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13830   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13831 }
13832
13833 /* look for redirect nodes, collect all redirect information and
13834  * process it.
13835  */
13836 static gboolean
13837 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13838 {
13839   GNode *rmra, *rmda, *rdrf;
13840
13841   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13842   if (rmra) {
13843     GList *redirects = NULL;
13844
13845     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13846     while (rmda) {
13847       GstQtReference ref = { NULL, NULL, 0, 0 };
13848       GNode *rmdr, *rmvc;
13849
13850       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13851         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13852         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13853             ref.min_req_bitrate);
13854       }
13855
13856       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13857         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13858         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13859
13860 #ifndef GST_DISABLE_GST_DEBUG
13861         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13862 #endif
13863         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13864
13865         GST_LOG_OBJECT (qtdemux,
13866             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13867             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13868             bitmask, check_type);
13869         if (package == FOURCC_qtim && check_type == 0) {
13870           ref.min_req_qt_version = version;
13871         }
13872       }
13873
13874       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13875       if (rdrf) {
13876         guint32 ref_type;
13877         guint8 *ref_data;
13878         guint ref_len;
13879
13880         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13881         if (ref_len > 20) {
13882           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13883           ref_data = (guint8 *) rdrf->data + 20;
13884           if (ref_type == FOURCC_alis) {
13885             guint record_len, record_version, fn_len;
13886
13887             if (ref_len > 70) {
13888               /* MacOSX alias record, google for alias-layout.txt */
13889               record_len = QT_UINT16 (ref_data + 4);
13890               record_version = QT_UINT16 (ref_data + 4 + 2);
13891               fn_len = QT_UINT8 (ref_data + 50);
13892               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13893                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13894               }
13895             } else {
13896               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13897                   ref_len);
13898             }
13899           } else if (ref_type == FOURCC_url_) {
13900             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13901           } else {
13902             GST_DEBUG_OBJECT (qtdemux,
13903                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13904                 GST_FOURCC_ARGS (ref_type));
13905           }
13906           if (ref.location != NULL) {
13907             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13908             redirects =
13909                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13910           } else {
13911             GST_WARNING_OBJECT (qtdemux,
13912                 "Failed to extract redirect location from rdrf atom");
13913           }
13914         } else {
13915           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13916         }
13917       }
13918
13919       /* look for others */
13920       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13921     }
13922
13923     if (redirects != NULL) {
13924       qtdemux_process_redirects (qtdemux, redirects);
13925     }
13926   }
13927   return TRUE;
13928 }
13929
13930 static GstTagList *
13931 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13932 {
13933   const gchar *fmt;
13934
13935   if (tags == NULL) {
13936     tags = gst_tag_list_new_empty ();
13937     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13938   }
13939
13940   if (qtdemux->major_brand == FOURCC_mjp2)
13941     fmt = "Motion JPEG 2000";
13942   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13943     fmt = "3GP";
13944   else if (qtdemux->major_brand == FOURCC_qt__)
13945     fmt = "Quicktime";
13946   else if (qtdemux->fragmented)
13947     fmt = "ISO fMP4";
13948   else
13949     fmt = "ISO MP4/M4A";
13950
13951   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13952       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13953
13954   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13955       fmt, NULL);
13956
13957   return tags;
13958 }
13959
13960 /* we have read the complete moov node now.
13961  * This function parses all of the relevant info, creates the traks and
13962  * prepares all data structures for playback
13963  */
13964 static gboolean
13965 qtdemux_parse_tree (GstQTDemux * qtdemux)
13966 {
13967   GNode *mvhd;
13968   GNode *trak;
13969   GNode *udta;
13970   GNode *mvex;
13971   GNode *pssh;
13972   guint64 creation_time;
13973   GstDateTime *datetime = NULL;
13974   gint version;
13975
13976   /* make sure we have a usable taglist */
13977   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13978
13979   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13980   if (mvhd == NULL) {
13981     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13982     return qtdemux_parse_redirects (qtdemux);
13983   }
13984
13985   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13986   if (version == 1) {
13987     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13988     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13989     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13990   } else if (version == 0) {
13991     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13992     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13993     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13994   } else {
13995     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13996     return FALSE;
13997   }
13998
13999   /* Moving qt creation time (secs since 1904) to unix time */
14000   if (creation_time != 0) {
14001     /* Try to use epoch first as it should be faster and more commonly found */
14002     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14003       gint64 now_s;
14004
14005       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14006       /* some data cleansing sanity */
14007       now_s = g_get_real_time () / G_USEC_PER_SEC;
14008       if (now_s + 24 * 3600 < creation_time) {
14009         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14010       } else {
14011         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14012       }
14013     } else {
14014       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14015       GDateTime *dt, *dt_local;
14016
14017       dt = g_date_time_add_seconds (base_dt, creation_time);
14018       dt_local = g_date_time_to_local (dt);
14019       datetime = gst_date_time_new_from_g_date_time (dt_local);
14020
14021       g_date_time_unref (base_dt);
14022       g_date_time_unref (dt);
14023     }
14024   }
14025   if (datetime) {
14026     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14027     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14028         datetime, NULL);
14029     gst_date_time_unref (datetime);
14030   }
14031
14032   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14033   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14034
14035   /* check for fragmented file and get some (default) data */
14036   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14037   if (mvex) {
14038     GNode *mehd;
14039     GstByteReader mehd_data;
14040
14041     /* let track parsing or anyone know weird stuff might happen ... */
14042     qtdemux->fragmented = TRUE;
14043
14044     /* compensate for total duration */
14045     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14046     if (mehd)
14047       qtdemux_parse_mehd (qtdemux, &mehd_data);
14048   }
14049
14050   /* Update the movie segment duration, unless it was directly given to us
14051    * by upstream. Otherwise let it as is, as we don't want to mangle the
14052    * duration provided by upstream that may come e.g. from a MPD file. */
14053   if (!qtdemux->upstream_format_is_time) {
14054     GstClockTime duration;
14055     /* set duration in the segment info */
14056     gst_qtdemux_get_duration (qtdemux, &duration);
14057     qtdemux->segment.duration = duration;
14058     /* also do not exceed duration; stop is set that way post seek anyway,
14059      * and segment activation falls back to duration,
14060      * whereas loop only checks stop, so let's align this here as well */
14061     qtdemux->segment.stop = duration;
14062   }
14063
14064   /* parse all traks */
14065   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14066   while (trak) {
14067     qtdemux_parse_trak (qtdemux, trak);
14068     /* iterate all siblings */
14069     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14070   }
14071
14072   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14073
14074   /* find tags */
14075   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14076   if (udta) {
14077     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14078   } else {
14079     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14080   }
14081
14082   /* maybe also some tags in meta box */
14083   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14084   if (udta) {
14085     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14086     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14087   } else {
14088     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14089   }
14090
14091   /* parse any protection system info */
14092   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14093   while (pssh) {
14094     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14095     qtdemux_parse_pssh (qtdemux, pssh);
14096     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14097   }
14098
14099   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14100
14101   return TRUE;
14102 }
14103
14104 /* taken from ffmpeg */
14105 static int
14106 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14107 {
14108   int count = 4;
14109   int len = 0;
14110
14111   while (count--) {
14112     int c;
14113
14114     if (ptr >= end)
14115       return -1;
14116
14117     c = *ptr++;
14118     len = (len << 7) | (c & 0x7f);
14119     if (!(c & 0x80))
14120       break;
14121   }
14122   *end_out = ptr;
14123   return len;
14124 }
14125
14126 static GList *
14127 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14128     gsize codec_data_size)
14129 {
14130   GList *list = NULL;
14131   guint8 *p = codec_data;
14132   gint i, offset, num_packets;
14133   guint *length, last;
14134
14135   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14136
14137   if (codec_data == NULL || codec_data_size == 0)
14138     goto error;
14139
14140   /* start of the stream and vorbis audio or theora video, need to
14141    * send the codec_priv data as first three packets */
14142   num_packets = p[0] + 1;
14143   GST_DEBUG_OBJECT (qtdemux,
14144       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14145       (guint) num_packets, codec_data_size);
14146
14147   /* Let's put some limits, Don't think there even is a xiph codec
14148    * with more than 3-4 headers */
14149   if (G_UNLIKELY (num_packets > 16)) {
14150     GST_WARNING_OBJECT (qtdemux,
14151         "Unlikely number of xiph headers, most likely not valid");
14152     goto error;
14153   }
14154
14155   length = g_alloca (num_packets * sizeof (guint));
14156   last = 0;
14157   offset = 1;
14158
14159   /* first packets, read length values */
14160   for (i = 0; i < num_packets - 1; i++) {
14161     length[i] = 0;
14162     while (offset < codec_data_size) {
14163       length[i] += p[offset];
14164       if (p[offset++] != 0xff)
14165         break;
14166     }
14167     last += length[i];
14168   }
14169   if (offset + last > codec_data_size)
14170     goto error;
14171
14172   /* last packet is the remaining size */
14173   length[i] = codec_data_size - offset - last;
14174
14175   for (i = 0; i < num_packets; i++) {
14176     GstBuffer *hdr;
14177
14178     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14179
14180     if (offset + length[i] > codec_data_size)
14181       goto error;
14182
14183     hdr = gst_buffer_new_memdup (p + offset, length[i]);
14184     list = g_list_append (list, hdr);
14185
14186     offset += length[i];
14187   }
14188
14189   return list;
14190
14191   /* ERRORS */
14192 error:
14193   {
14194     if (list != NULL)
14195       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14196     return NULL;
14197   }
14198
14199 }
14200
14201 /* this can change the codec originally present in @list */
14202 static void
14203 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14204     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14205 {
14206   int len = QT_UINT32 (esds->data);
14207   guint8 *ptr = esds->data;
14208   guint8 *end = ptr + len;
14209   int tag;
14210   guint8 *data_ptr = NULL;
14211   int data_len = 0;
14212   guint8 object_type_id = 0;
14213   guint8 stream_type = 0;
14214   const char *codec_name = NULL;
14215   GstCaps *caps = NULL;
14216
14217   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14218   ptr += 8;
14219   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14220   ptr += 4;
14221   while (ptr + 1 < end) {
14222     tag = QT_UINT8 (ptr);
14223     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14224     ptr++;
14225     len = read_descr_size (ptr, end, &ptr);
14226     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14227
14228     /* Check the stated amount of data is available for reading */
14229     if (len < 0 || ptr + len > end)
14230       break;
14231
14232     switch (tag) {
14233       case ES_DESCRIPTOR_TAG:
14234         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14235         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14236         ptr += 3;
14237         break;
14238       case DECODER_CONFIG_DESC_TAG:{
14239         guint max_bitrate, avg_bitrate;
14240
14241         object_type_id = QT_UINT8 (ptr);
14242         stream_type = QT_UINT8 (ptr + 1) >> 2;
14243         max_bitrate = QT_UINT32 (ptr + 5);
14244         avg_bitrate = QT_UINT32 (ptr + 9);
14245         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14246         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14247         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14248         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14249         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14250         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14251           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14252               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14253         }
14254         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14255           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14256               avg_bitrate, NULL);
14257         }
14258         ptr += 13;
14259         break;
14260       }
14261       case DECODER_SPECIFIC_INFO_TAG:
14262         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14263         if (object_type_id == 0xe0 && len == 0x40) {
14264           guint8 *data;
14265           GstStructure *s;
14266           guint32 clut[16];
14267           gint i;
14268
14269           GST_DEBUG_OBJECT (qtdemux,
14270               "Have VOBSUB palette. Creating palette event");
14271           /* move to decConfigDescr data and read palette */
14272           data = ptr;
14273           for (i = 0; i < 16; i++) {
14274             clut[i] = QT_UINT32 (data);
14275             data += 4;
14276           }
14277
14278           s = gst_structure_new ("application/x-gst-dvd", "event",
14279               G_TYPE_STRING, "dvd-spu-clut-change",
14280               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14281               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14282               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14283               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14284               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14285               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14286               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14287               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14288               NULL);
14289
14290           /* store event and trigger custom processing */
14291           stream->pending_event =
14292               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14293         } else {
14294           /* Generic codec_data handler puts it on the caps */
14295           data_ptr = ptr;
14296           data_len = len;
14297         }
14298
14299         ptr += len;
14300         break;
14301       case SL_CONFIG_DESC_TAG:
14302         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14303         ptr += 1;
14304         break;
14305       default:
14306         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14307             tag);
14308         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14309         ptr += len;
14310         break;
14311     }
14312   }
14313
14314   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14315    * in use, and should also be used to override some other parameters for some
14316    * codecs. */
14317   switch (object_type_id) {
14318     case 0x20:                 /* MPEG-4 */
14319       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14320        * profile_and_level_indication */
14321       if (data_ptr != NULL && data_len >= 5 &&
14322           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14323         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14324             data_ptr + 4, data_len - 4);
14325       }
14326       break;                    /* Nothing special needed here */
14327     case 0x21:                 /* H.264 */
14328       codec_name = "H.264 / AVC";
14329       caps = gst_caps_new_simple ("video/x-h264",
14330           "stream-format", G_TYPE_STRING, "avc",
14331           "alignment", G_TYPE_STRING, "au", NULL);
14332       break;
14333     case 0x40:                 /* AAC (any) */
14334     case 0x66:                 /* AAC Main */
14335     case 0x67:                 /* AAC LC */
14336     case 0x68:                 /* AAC SSR */
14337       /* Override channels and rate based on the codec_data, as it's often
14338        * wrong. */
14339       /* Only do so for basic setup without HE-AAC extension */
14340       if (data_ptr && data_len == 2) {
14341         guint channels, rate;
14342
14343         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14344         if (channels > 0)
14345           entry->n_channels = channels;
14346
14347         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14348         if (rate > 0)
14349           entry->rate = rate;
14350       }
14351
14352       /* Set level and profile if possible */
14353       if (data_ptr != NULL && data_len >= 2) {
14354         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14355             data_ptr, data_len);
14356       } else {
14357         const gchar *profile_str = NULL;
14358         GstBuffer *buffer;
14359         GstMapInfo map;
14360         guint8 *codec_data;
14361         gint rate_idx, profile;
14362
14363         /* No codec_data, let's invent something.
14364          * FIXME: This is wrong for SBR! */
14365
14366         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14367
14368         buffer = gst_buffer_new_and_alloc (2);
14369         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14370         codec_data = map.data;
14371
14372         rate_idx =
14373             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14374             (stream)->rate);
14375
14376         switch (object_type_id) {
14377           case 0x66:
14378             profile_str = "main";
14379             profile = 0;
14380             break;
14381           case 0x67:
14382             profile_str = "lc";
14383             profile = 1;
14384             break;
14385           case 0x68:
14386             profile_str = "ssr";
14387             profile = 2;
14388             break;
14389           default:
14390             profile = 3;
14391             break;
14392         }
14393
14394         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14395         codec_data[1] =
14396             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14397
14398         gst_buffer_unmap (buffer, &map);
14399         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14400             GST_TYPE_BUFFER, buffer, NULL);
14401         gst_buffer_unref (buffer);
14402
14403         if (profile_str) {
14404           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14405               G_TYPE_STRING, profile_str, NULL);
14406         }
14407       }
14408       break;
14409     case 0x60:                 /* MPEG-2, various profiles */
14410     case 0x61:
14411     case 0x62:
14412     case 0x63:
14413     case 0x64:
14414     case 0x65:
14415       codec_name = "MPEG-2 video";
14416       caps = gst_caps_new_simple ("video/mpeg",
14417           "mpegversion", G_TYPE_INT, 2,
14418           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14419       break;
14420     case 0x69:                 /* MPEG-2 BC audio */
14421     case 0x6B:                 /* MPEG-1 audio */
14422       caps = gst_caps_new_simple ("audio/mpeg",
14423           "mpegversion", G_TYPE_INT, 1, NULL);
14424       codec_name = "MPEG-1 audio";
14425       break;
14426     case 0x6A:                 /* MPEG-1 */
14427       codec_name = "MPEG-1 video";
14428       caps = gst_caps_new_simple ("video/mpeg",
14429           "mpegversion", G_TYPE_INT, 1,
14430           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14431       break;
14432     case 0x6C:                 /* MJPEG */
14433       caps =
14434           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14435           NULL);
14436       codec_name = "Motion-JPEG";
14437       break;
14438     case 0x6D:                 /* PNG */
14439       caps =
14440           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14441           NULL);
14442       codec_name = "PNG still images";
14443       break;
14444     case 0x6E:                 /* JPEG2000 */
14445       codec_name = "JPEG-2000";
14446       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14447       break;
14448     case 0xA4:                 /* Dirac */
14449       codec_name = "Dirac";
14450       caps = gst_caps_new_empty_simple ("video/x-dirac");
14451       break;
14452     case 0xA5:                 /* AC3 */
14453       codec_name = "AC-3 audio";
14454       caps = gst_caps_new_simple ("audio/x-ac3",
14455           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14456       break;
14457     case 0xA9:                 /* AC3 */
14458       codec_name = "DTS audio";
14459       caps = gst_caps_new_simple ("audio/x-dts",
14460           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14461       break;
14462     case 0xDD:
14463       if (stream_type == 0x05 && data_ptr) {
14464         GList *headers =
14465             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14466         if (headers) {
14467           GList *tmp;
14468           GValue arr_val = G_VALUE_INIT;
14469           GValue buf_val = G_VALUE_INIT;
14470           GstStructure *s;
14471
14472           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14473           codec_name = "Vorbis";
14474           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14475           g_value_init (&arr_val, GST_TYPE_ARRAY);
14476           g_value_init (&buf_val, GST_TYPE_BUFFER);
14477           for (tmp = headers; tmp; tmp = tmp->next) {
14478             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14479             gst_value_array_append_value (&arr_val, &buf_val);
14480           }
14481           s = gst_caps_get_structure (caps, 0);
14482           gst_structure_take_value (s, "streamheader", &arr_val);
14483           g_value_unset (&buf_val);
14484           g_list_free (headers);
14485
14486           data_ptr = NULL;
14487           data_len = 0;
14488         }
14489       }
14490       break;
14491     case 0xE1:                 /* QCELP */
14492       /* QCELP, the codec_data is a riff tag (little endian) with
14493        * 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). */
14494       caps = gst_caps_new_empty_simple ("audio/qcelp");
14495       codec_name = "QCELP";
14496       break;
14497     default:
14498       break;
14499   }
14500
14501   /* If we have a replacement caps, then change our caps for this stream */
14502   if (caps) {
14503     gst_caps_unref (entry->caps);
14504     entry->caps = caps;
14505   }
14506
14507   if (codec_name && list)
14508     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14509         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14510
14511   /* Add the codec_data attribute to caps, if we have it */
14512   if (data_ptr) {
14513     GstBuffer *buffer;
14514
14515     buffer = gst_buffer_new_and_alloc (data_len);
14516     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14517
14518     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14519     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14520
14521     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14522         buffer, NULL);
14523     gst_buffer_unref (buffer);
14524   }
14525
14526 }
14527
14528 static inline GstCaps *
14529 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14530 {
14531   GstCaps *caps;
14532   guint i;
14533   char *s, fourstr[5];
14534
14535   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14536   for (i = 0; i < 4; i++) {
14537     if (!g_ascii_isalnum (fourstr[i]))
14538       fourstr[i] = '_';
14539   }
14540   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14541   caps = gst_caps_new_empty_simple (s);
14542   g_free (s);
14543   return caps;
14544 }
14545
14546 #define _codec(name) \
14547   do { \
14548     if (codec_name) { \
14549       *codec_name = g_strdup (name); \
14550     } \
14551   } while (0)
14552
14553 static GstCaps *
14554 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14555     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14556     const guint8 * stsd_entry_data, gchar ** codec_name)
14557 {
14558   GstCaps *caps = NULL;
14559   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14560
14561   switch (fourcc) {
14562     case FOURCC_png:
14563       _codec ("PNG still images");
14564       caps = gst_caps_new_empty_simple ("image/png");
14565       break;
14566     case FOURCC_jpeg:
14567       _codec ("JPEG still images");
14568       caps =
14569           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14570           NULL);
14571       break;
14572     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14573     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14574     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14575     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14576       _codec ("Motion-JPEG");
14577       caps =
14578           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14579           NULL);
14580       break;
14581     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14582       _codec ("Motion-JPEG format B");
14583       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14584       break;
14585     case FOURCC_mjp2:
14586       _codec ("JPEG-2000");
14587       /* override to what it should be according to spec, avoid palette_data */
14588       entry->bits_per_sample = 24;
14589       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14590       break;
14591     case FOURCC_SVQ3:
14592       _codec ("Sorensen video v.3");
14593       caps = gst_caps_new_simple ("video/x-svq",
14594           "svqversion", G_TYPE_INT, 3, NULL);
14595       break;
14596     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14597     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14598       _codec ("Sorensen video v.1");
14599       caps = gst_caps_new_simple ("video/x-svq",
14600           "svqversion", G_TYPE_INT, 1, NULL);
14601       break;
14602     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14603       caps = gst_caps_new_empty_simple ("video/x-raw");
14604       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14605       _codec ("Windows Raw RGB");
14606       stream->alignment = 32;
14607       break;
14608     case FOURCC_raw_:
14609     {
14610       guint16 bps;
14611
14612       bps = QT_UINT16 (stsd_entry_data + 82);
14613       switch (bps) {
14614         case 15:
14615           format = GST_VIDEO_FORMAT_RGB15;
14616           break;
14617         case 16:
14618           format = GST_VIDEO_FORMAT_RGB16;
14619           break;
14620         case 24:
14621           format = GST_VIDEO_FORMAT_RGB;
14622           break;
14623         case 32:
14624           format = GST_VIDEO_FORMAT_ARGB;
14625           break;
14626         default:
14627           /* unknown */
14628           break;
14629       }
14630       break;
14631     }
14632     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14633       format = GST_VIDEO_FORMAT_I420;
14634       break;
14635     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14636     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14637       format = GST_VIDEO_FORMAT_I420;
14638       break;
14639     case FOURCC_2vuy:
14640     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14641       format = GST_VIDEO_FORMAT_UYVY;
14642       break;
14643     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14644       format = GST_VIDEO_FORMAT_v308;
14645       break;
14646     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14647       format = GST_VIDEO_FORMAT_v216;
14648       break;
14649     case FOURCC_v210:
14650       format = GST_VIDEO_FORMAT_v210;
14651       break;
14652     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14653       format = GST_VIDEO_FORMAT_r210;
14654       break;
14655       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14656          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14657          format = GST_VIDEO_FORMAT_v410;
14658          break;
14659        */
14660       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14661        * but different order than AYUV
14662        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14663        format = GST_VIDEO_FORMAT_v408;
14664        break;
14665        */
14666     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14667     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14668       _codec ("MPEG-1 video");
14669       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14670           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14671       break;
14672     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14673     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14674     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14675     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14676     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14677     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14678     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14679     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14680     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14681     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14682     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14683     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14684     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14685     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14686     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14687     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14688     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14689     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14690     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14691     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14692     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14693     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14694     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14695     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14696     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14697     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14698     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14699     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14700     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14701     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14702     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14703     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14704     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14705     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14706     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14707     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14708     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14709     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14710     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14711     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14712     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14713     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14714     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14715     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14716     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14717     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14718     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14719       _codec ("MPEG-2 video");
14720       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14721           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14722       break;
14723     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14724       _codec ("GIF still images");
14725       caps = gst_caps_new_empty_simple ("image/gif");
14726       break;
14727     case FOURCC_h263:
14728     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14729     case FOURCC_s263:
14730     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14731       _codec ("H.263");
14732       /* ffmpeg uses the height/width props, don't know why */
14733       caps = gst_caps_new_simple ("video/x-h263",
14734           "variant", G_TYPE_STRING, "itu", NULL);
14735       break;
14736     case FOURCC_mp4v:
14737     case FOURCC_MP4V:
14738       _codec ("MPEG-4 video");
14739       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14740           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14741       break;
14742     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14743     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14744       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14745       caps = gst_caps_new_simple ("video/x-msmpeg",
14746           "msmpegversion", G_TYPE_INT, 43, NULL);
14747       break;
14748     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14749       _codec ("DivX 3");
14750       caps = gst_caps_new_simple ("video/x-divx",
14751           "divxversion", G_TYPE_INT, 3, NULL);
14752       break;
14753     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14754     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14755       _codec ("DivX 4");
14756       caps = gst_caps_new_simple ("video/x-divx",
14757           "divxversion", G_TYPE_INT, 4, NULL);
14758       break;
14759     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14760       _codec ("DivX 5");
14761       caps = gst_caps_new_simple ("video/x-divx",
14762           "divxversion", G_TYPE_INT, 5, NULL);
14763       break;
14764
14765     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14766       _codec ("FFV1");
14767       caps = gst_caps_new_simple ("video/x-ffv",
14768           "ffvversion", G_TYPE_INT, 1, NULL);
14769       break;
14770
14771     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14772     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14773     case FOURCC_XVID:
14774     case FOURCC_xvid:
14775     case FOURCC_FMP4:
14776     case FOURCC_fmp4:
14777     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14778       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14779           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14780       _codec ("MPEG-4");
14781       break;
14782
14783     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14784       _codec ("Cinepak");
14785       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14786       break;
14787     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14788       _codec ("Apple QuickDraw");
14789       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14790       break;
14791     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14792       _codec ("Apple video");
14793       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14794       break;
14795     case FOURCC_H264:
14796     case FOURCC_avc1:
14797     case FOURCC_dva1:
14798       _codec ("H.264 / AVC");
14799       caps = gst_caps_new_simple ("video/x-h264",
14800           "stream-format", G_TYPE_STRING, "avc",
14801           "alignment", G_TYPE_STRING, "au", NULL);
14802       break;
14803     case FOURCC_avc3:
14804     case FOURCC_dvav:
14805       _codec ("H.264 / AVC");
14806       caps = gst_caps_new_simple ("video/x-h264",
14807           "stream-format", G_TYPE_STRING, "avc3",
14808           "alignment", G_TYPE_STRING, "au", NULL);
14809       break;
14810     case FOURCC_H265:
14811     case FOURCC_hvc1:
14812     case FOURCC_dvh1:
14813       _codec ("H.265 / HEVC");
14814       caps = gst_caps_new_simple ("video/x-h265",
14815           "stream-format", G_TYPE_STRING, "hvc1",
14816           "alignment", G_TYPE_STRING, "au", NULL);
14817       break;
14818     case FOURCC_hev1:
14819     case FOURCC_dvhe:
14820       _codec ("H.265 / HEVC");
14821       caps = gst_caps_new_simple ("video/x-h265",
14822           "stream-format", G_TYPE_STRING, "hev1",
14823           "alignment", G_TYPE_STRING, "au", NULL);
14824       break;
14825     case FOURCC_rle_:
14826       _codec ("Run-length encoding");
14827       caps = gst_caps_new_simple ("video/x-rle",
14828           "layout", G_TYPE_STRING, "quicktime", NULL);
14829       break;
14830     case FOURCC_WRLE:
14831       _codec ("Run-length encoding");
14832       caps = gst_caps_new_simple ("video/x-rle",
14833           "layout", G_TYPE_STRING, "microsoft", NULL);
14834       break;
14835     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14836     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14837       _codec ("Indeo Video 3");
14838       caps = gst_caps_new_simple ("video/x-indeo",
14839           "indeoversion", G_TYPE_INT, 3, NULL);
14840       break;
14841     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14842     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14843       _codec ("Intel Video 4");
14844       caps = gst_caps_new_simple ("video/x-indeo",
14845           "indeoversion", G_TYPE_INT, 4, NULL);
14846       break;
14847     case FOURCC_dvcp:
14848     case FOURCC_dvc_:
14849     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14850     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14851     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14852     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14853     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14854     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14855       _codec ("DV Video");
14856       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14857           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14858       break;
14859     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14860     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14861       _codec ("DVCPro50 Video");
14862       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14863           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14864       break;
14865     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14866     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14867       _codec ("DVCProHD Video");
14868       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14869           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14870       break;
14871     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14872       _codec ("Apple Graphics (SMC)");
14873       caps = gst_caps_new_empty_simple ("video/x-smc");
14874       break;
14875     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14876       _codec ("VP3");
14877       caps = gst_caps_new_empty_simple ("video/x-vp3");
14878       break;
14879     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14880       _codec ("VP6 Flash");
14881       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14882       break;
14883     case FOURCC_XiTh:
14884       _codec ("Theora");
14885       caps = gst_caps_new_empty_simple ("video/x-theora");
14886       /* theora uses one byte of padding in the data stream because it does not
14887        * allow 0 sized packets while theora does */
14888       entry->padding = 1;
14889       break;
14890     case FOURCC_drac:
14891       _codec ("Dirac");
14892       caps = gst_caps_new_empty_simple ("video/x-dirac");
14893       break;
14894     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14895       _codec ("TIFF still images");
14896       caps = gst_caps_new_empty_simple ("image/tiff");
14897       break;
14898     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14899       _codec ("Apple Intermediate Codec");
14900       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14901       break;
14902     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14903       _codec ("AVID DNxHD");
14904       caps = gst_caps_from_string ("video/x-dnxhd");
14905       break;
14906     case FOURCC_VP80:
14907     case FOURCC_vp08:
14908       _codec ("On2 VP8");
14909       caps = gst_caps_from_string ("video/x-vp8");
14910       break;
14911     case FOURCC_vp09:
14912       _codec ("Google VP9");
14913       caps = gst_caps_from_string ("video/x-vp9");
14914       break;
14915     case FOURCC_apcs:
14916       _codec ("Apple ProRes LT");
14917       caps =
14918           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14919           NULL);
14920       break;
14921     case FOURCC_apch:
14922       _codec ("Apple ProRes HQ");
14923       caps =
14924           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14925           NULL);
14926       break;
14927     case FOURCC_apcn:
14928       _codec ("Apple ProRes");
14929       caps =
14930           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14931           "standard", NULL);
14932       break;
14933     case FOURCC_apco:
14934       _codec ("Apple ProRes Proxy");
14935       caps =
14936           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14937           "proxy", NULL);
14938       break;
14939     case FOURCC_ap4h:
14940       _codec ("Apple ProRes 4444");
14941       caps =
14942           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14943           "4444", NULL);
14944
14945       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14946       if (entry->bits_per_sample > 0) {
14947         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14948             NULL);
14949       }
14950       break;
14951     case FOURCC_ap4x:
14952       _codec ("Apple ProRes 4444 XQ");
14953       caps =
14954           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14955           "4444xq", NULL);
14956
14957       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14958       if (entry->bits_per_sample > 0) {
14959         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14960             NULL);
14961       }
14962       break;
14963     case FOURCC_cfhd:
14964       _codec ("GoPro CineForm");
14965       caps = gst_caps_from_string ("video/x-cineform");
14966       break;
14967     case FOURCC_vc_1:
14968     case FOURCC_ovc1:
14969       _codec ("VC-1");
14970       caps = gst_caps_new_simple ("video/x-wmv",
14971           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14972       break;
14973     case FOURCC_av01:
14974       _codec ("AV1");
14975       caps = gst_caps_new_simple ("video/x-av1",
14976           "alignment", G_TYPE_STRING, "tu", NULL);
14977       break;
14978     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14979     default:
14980     {
14981       caps = _get_unknown_codec_name ("video", fourcc);
14982       break;
14983     }
14984   }
14985
14986   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14987     GstVideoInfo info;
14988
14989     gst_video_info_init (&info);
14990     gst_video_info_set_format (&info, format, entry->width, entry->height);
14991
14992     caps = gst_video_info_to_caps (&info);
14993     *codec_name = gst_pb_utils_get_codec_description (caps);
14994
14995     /* enable clipping for raw video streams */
14996     stream->need_clip = TRUE;
14997     stream->alignment = 32;
14998   }
14999
15000   return caps;
15001 }
15002
15003 static guint
15004 round_up_pow2 (guint n)
15005 {
15006   n = n - 1;
15007   n = n | (n >> 1);
15008   n = n | (n >> 2);
15009   n = n | (n >> 4);
15010   n = n | (n >> 8);
15011   n = n | (n >> 16);
15012   return n + 1;
15013 }
15014
15015 static GstCaps *
15016 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15017     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15018     int len, gchar ** codec_name)
15019 {
15020   GstCaps *caps;
15021   const GstStructure *s;
15022   const gchar *name;
15023   gint endian = 0;
15024   GstAudioFormat format = 0;
15025   gint depth;
15026
15027   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15028
15029   depth = entry->bytes_per_packet * 8;
15030
15031   switch (fourcc) {
15032     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15033     case FOURCC_raw_:
15034       /* 8-bit audio is unsigned */
15035       if (depth == 8)
15036         format = GST_AUDIO_FORMAT_U8;
15037       /* otherwise it's signed and big-endian just like 'twos' */
15038     case FOURCC_twos:
15039       endian = G_BIG_ENDIAN;
15040       /* fall-through */
15041     case FOURCC_sowt:
15042     {
15043       gchar *str;
15044
15045       if (!endian)
15046         endian = G_LITTLE_ENDIAN;
15047
15048       if (!format)
15049         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15050
15051       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15052       _codec (str);
15053       g_free (str);
15054
15055       caps = gst_caps_new_simple ("audio/x-raw",
15056           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15057           "layout", G_TYPE_STRING, "interleaved", NULL);
15058       stream->alignment = GST_ROUND_UP_8 (depth);
15059       stream->alignment = round_up_pow2 (stream->alignment);
15060       break;
15061     }
15062     case FOURCC_fl64:
15063       _codec ("Raw 64-bit floating-point audio");
15064       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15065        * endian later */
15066       caps = gst_caps_new_simple ("audio/x-raw",
15067           "format", G_TYPE_STRING, "F64BE",
15068           "layout", G_TYPE_STRING, "interleaved", NULL);
15069       stream->alignment = 8;
15070       break;
15071     case FOURCC_fl32:
15072       _codec ("Raw 32-bit floating-point audio");
15073       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15074        * endian later */
15075       caps = gst_caps_new_simple ("audio/x-raw",
15076           "format", G_TYPE_STRING, "F32BE",
15077           "layout", G_TYPE_STRING, "interleaved", NULL);
15078       stream->alignment = 4;
15079       break;
15080     case FOURCC_in24:
15081       _codec ("Raw 24-bit PCM audio");
15082       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15083        * endian later */
15084       caps = gst_caps_new_simple ("audio/x-raw",
15085           "format", G_TYPE_STRING, "S24BE",
15086           "layout", G_TYPE_STRING, "interleaved", NULL);
15087       stream->alignment = 4;
15088       break;
15089     case FOURCC_in32:
15090       _codec ("Raw 32-bit PCM audio");
15091       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15092        * endian later */
15093       caps = gst_caps_new_simple ("audio/x-raw",
15094           "format", G_TYPE_STRING, "S32BE",
15095           "layout", G_TYPE_STRING, "interleaved", NULL);
15096       stream->alignment = 4;
15097       break;
15098     case FOURCC_s16l:
15099       _codec ("Raw 16-bit PCM audio");
15100       caps = gst_caps_new_simple ("audio/x-raw",
15101           "format", G_TYPE_STRING, "S16LE",
15102           "layout", G_TYPE_STRING, "interleaved", NULL);
15103       stream->alignment = 2;
15104       break;
15105     case FOURCC_ulaw:
15106       _codec ("Mu-law audio");
15107       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15108       break;
15109     case FOURCC_alaw:
15110       _codec ("A-law audio");
15111       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15112       break;
15113     case 0x0200736d:
15114     case 0x6d730002:
15115       _codec ("Microsoft ADPCM");
15116       /* Microsoft ADPCM-ACM code 2 */
15117       caps = gst_caps_new_simple ("audio/x-adpcm",
15118           "layout", G_TYPE_STRING, "microsoft", NULL);
15119       break;
15120     case 0x1100736d:
15121     case 0x6d730011:
15122       _codec ("DVI/IMA ADPCM");
15123       caps = gst_caps_new_simple ("audio/x-adpcm",
15124           "layout", G_TYPE_STRING, "dvi", NULL);
15125       break;
15126     case 0x1700736d:
15127     case 0x6d730017:
15128       _codec ("DVI/Intel IMA ADPCM");
15129       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15130       caps = gst_caps_new_simple ("audio/x-adpcm",
15131           "layout", G_TYPE_STRING, "quicktime", NULL);
15132       break;
15133     case 0x5500736d:
15134     case 0x6d730055:
15135       /* MPEG layer 3, CBR only (pre QT4.1) */
15136     case FOURCC__mp3:
15137     case FOURCC_mp3_:
15138       _codec ("MPEG-1 layer 3");
15139       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15140       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15141           "mpegversion", G_TYPE_INT, 1, NULL);
15142       break;
15143     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15144       _codec ("MPEG-1 layer 2");
15145       /* MPEG layer 2 */
15146       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15147           "mpegversion", G_TYPE_INT, 1, NULL);
15148       break;
15149     case 0x20736d:
15150     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15151       _codec ("EAC-3 audio");
15152       caps = gst_caps_new_simple ("audio/x-eac3",
15153           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15154       entry->sampled = TRUE;
15155       break;
15156     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15157     case FOURCC_ac_3:
15158       _codec ("AC-3 audio");
15159       caps = gst_caps_new_simple ("audio/x-ac3",
15160           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15161       entry->sampled = TRUE;
15162       break;
15163     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15164     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15165       _codec ("DTS audio");
15166       caps = gst_caps_new_simple ("audio/x-dts",
15167           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15168       entry->sampled = TRUE;
15169       break;
15170     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15171     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15172       _codec ("DTS-HD audio");
15173       caps = gst_caps_new_simple ("audio/x-dts",
15174           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15175       entry->sampled = TRUE;
15176       break;
15177     case FOURCC_MAC3:
15178       _codec ("MACE-3");
15179       caps = gst_caps_new_simple ("audio/x-mace",
15180           "maceversion", G_TYPE_INT, 3, NULL);
15181       break;
15182     case FOURCC_MAC6:
15183       _codec ("MACE-6");
15184       caps = gst_caps_new_simple ("audio/x-mace",
15185           "maceversion", G_TYPE_INT, 6, NULL);
15186       break;
15187     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15188       /* ogg/vorbis */
15189       caps = gst_caps_new_empty_simple ("application/ogg");
15190       break;
15191     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15192       _codec ("DV audio");
15193       caps = gst_caps_new_empty_simple ("audio/x-dv");
15194       break;
15195     case FOURCC_mp4a:
15196       _codec ("MPEG-4 AAC audio");
15197       caps = gst_caps_new_simple ("audio/mpeg",
15198           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15199           "stream-format", G_TYPE_STRING, "raw", NULL);
15200       break;
15201     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15202       _codec ("QDesign Music");
15203       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15204       break;
15205     case FOURCC_QDM2:
15206       _codec ("QDesign Music v.2");
15207       /* FIXME: QDesign music version 2 (no constant) */
15208       if (FALSE && data) {
15209         caps = gst_caps_new_simple ("audio/x-qdm2",
15210             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15211             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15212             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15213       } else {
15214         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15215       }
15216       break;
15217     case FOURCC_agsm:
15218       _codec ("GSM audio");
15219       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15220       break;
15221     case FOURCC_samr:
15222       _codec ("AMR audio");
15223       caps = gst_caps_new_empty_simple ("audio/AMR");
15224       break;
15225     case FOURCC_sawb:
15226       _codec ("AMR-WB audio");
15227       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15228       break;
15229     case FOURCC_ima4:
15230       _codec ("Quicktime IMA ADPCM");
15231       caps = gst_caps_new_simple ("audio/x-adpcm",
15232           "layout", G_TYPE_STRING, "quicktime", NULL);
15233       break;
15234     case FOURCC_alac:
15235       _codec ("Apple lossless audio");
15236       caps = gst_caps_new_empty_simple ("audio/x-alac");
15237       break;
15238     case FOURCC_fLaC:
15239       _codec ("Free Lossless Audio Codec");
15240       caps = gst_caps_new_simple ("audio/x-flac",
15241           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15242       break;
15243     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15244       _codec ("QualComm PureVoice");
15245       caps = gst_caps_from_string ("audio/qcelp");
15246       break;
15247     case FOURCC_wma_:
15248     case FOURCC_owma:
15249       _codec ("WMA");
15250       caps = gst_caps_new_empty_simple ("audio/x-wma");
15251       break;
15252     case FOURCC_opus:
15253       _codec ("Opus");
15254       caps = gst_caps_new_empty_simple ("audio/x-opus");
15255       break;
15256     case FOURCC_lpcm:
15257     {
15258       guint32 flags = 0;
15259       guint32 depth = 0;
15260       guint32 width = 0;
15261       GstAudioFormat format;
15262       enum
15263       {
15264         FLAG_IS_FLOAT = 0x1,
15265         FLAG_IS_BIG_ENDIAN = 0x2,
15266         FLAG_IS_SIGNED = 0x4,
15267         FLAG_IS_PACKED = 0x8,
15268         FLAG_IS_ALIGNED_HIGH = 0x10,
15269         FLAG_IS_NON_INTERLEAVED = 0x20
15270       };
15271       _codec ("Raw LPCM audio");
15272
15273       if (data && len >= 36) {
15274         depth = QT_UINT32 (data + 24);
15275         flags = QT_UINT32 (data + 28);
15276         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15277       }
15278       if ((flags & FLAG_IS_FLOAT) == 0) {
15279         if (depth == 0)
15280           depth = 16;
15281         if (width == 0)
15282           width = 16;
15283         if ((flags & FLAG_IS_ALIGNED_HIGH))
15284           depth = width;
15285
15286         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15287             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15288             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15289         caps = gst_caps_new_simple ("audio/x-raw",
15290             "format", G_TYPE_STRING,
15291             format !=
15292             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15293             "UNKNOWN", "layout", G_TYPE_STRING,
15294             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15295             "interleaved", NULL);
15296         stream->alignment = GST_ROUND_UP_8 (depth);
15297         stream->alignment = round_up_pow2 (stream->alignment);
15298       } else {
15299         if (width == 0)
15300           width = 32;
15301         if (width == 64) {
15302           if (flags & FLAG_IS_BIG_ENDIAN)
15303             format = GST_AUDIO_FORMAT_F64BE;
15304           else
15305             format = GST_AUDIO_FORMAT_F64LE;
15306         } else {
15307           if (flags & FLAG_IS_BIG_ENDIAN)
15308             format = GST_AUDIO_FORMAT_F32BE;
15309           else
15310             format = GST_AUDIO_FORMAT_F32LE;
15311         }
15312         caps = gst_caps_new_simple ("audio/x-raw",
15313             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15314             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15315             "non-interleaved" : "interleaved", NULL);
15316         stream->alignment = width / 8;
15317       }
15318       break;
15319     }
15320     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
15321     {
15322       _codec ("AC4");
15323       caps = gst_caps_new_empty_simple ("audio/x-ac4");
15324       break;
15325     }
15326     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15327       /* ? */
15328     default:
15329     {
15330       caps = _get_unknown_codec_name ("audio", fourcc);
15331       break;
15332     }
15333   }
15334
15335   if (caps) {
15336     GstCaps *templ_caps =
15337         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15338     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15339     gst_caps_unref (caps);
15340     gst_caps_unref (templ_caps);
15341     caps = intersection;
15342   }
15343
15344   /* enable clipping for raw audio streams */
15345   s = gst_caps_get_structure (caps, 0);
15346   name = gst_structure_get_name (s);
15347   if (g_str_has_prefix (name, "audio/x-raw")) {
15348     stream->need_clip = TRUE;
15349     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
15350     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15351     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15352         stream->max_buffer_size);
15353   }
15354   return caps;
15355 }
15356
15357 static GstCaps *
15358 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15359     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15360     const guint8 * stsd_entry_data, gchar ** codec_name)
15361 {
15362   GstCaps *caps;
15363
15364   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15365
15366   switch (fourcc) {
15367     case FOURCC_mp4s:
15368       _codec ("DVD subtitle");
15369       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15370       stream->process_func = gst_qtdemux_process_buffer_dvd;
15371       break;
15372     case FOURCC_text:
15373       _codec ("Quicktime timed text");
15374       goto text;
15375     case FOURCC_tx3g:
15376       _codec ("3GPP timed text");
15377     text:
15378       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15379           "utf8", NULL);
15380       /* actual text piece needs to be extracted */
15381       stream->process_func = gst_qtdemux_process_buffer_text;
15382       break;
15383     case FOURCC_stpp:
15384       _codec ("XML subtitles");
15385       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15386       break;
15387     case FOURCC_wvtt:
15388     {
15389       GstBuffer *buffer;
15390       const gchar *buf = "WEBVTT\n\n";
15391
15392       _codec ("WebVTT subtitles");
15393       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15394       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15395
15396       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15397       buffer = gst_buffer_new_and_alloc (8);
15398       gst_buffer_fill (buffer, 0, buf, 8);
15399       stream->buffers = g_slist_append (stream->buffers, buffer);
15400
15401       break;
15402     }
15403     case FOURCC_c608:
15404       _codec ("CEA 608 Closed Caption");
15405       caps =
15406           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15407           G_TYPE_STRING, "s334-1a", NULL);
15408       stream->process_func = gst_qtdemux_process_buffer_clcp;
15409       stream->need_split = TRUE;
15410       break;
15411     case FOURCC_c708:
15412       _codec ("CEA 708 Closed Caption");
15413       caps =
15414           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15415           G_TYPE_STRING, "cdp", NULL);
15416       stream->process_func = gst_qtdemux_process_buffer_clcp;
15417       break;
15418
15419     default:
15420     {
15421       caps = _get_unknown_codec_name ("text", fourcc);
15422       break;
15423     }
15424   }
15425   return caps;
15426 }
15427
15428 static GstCaps *
15429 qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15430     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15431     const guint8 * stsd_entry_data, gchar ** codec_name)
15432 {
15433   GstCaps *caps = NULL;
15434
15435   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15436
15437   switch (fourcc) {
15438     case FOURCC_metx:{
15439       gsize size = QT_UINT32 (stsd_entry_data);
15440       GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
15441       const gchar *content_encoding;
15442       const gchar *namespaces;
15443       const gchar *schema_locations;
15444
15445       if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
15446         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15447         break;
15448       }
15449
15450       if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
15451           !gst_byte_reader_get_string (&reader, &namespaces) ||
15452           !gst_byte_reader_get_string (&reader, &schema_locations)) {
15453         GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
15454         break;
15455       }
15456
15457       if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
15458         if (content_encoding == NULL || *content_encoding == '\0'
15459             || g_ascii_strcasecmp (content_encoding, "xml") == 0) {
15460           _codec ("ONVIF Timed XML MetaData");
15461           caps =
15462               gst_caps_new_simple ("application/x-onvif-metadata", "parsed",
15463               G_TYPE_BOOLEAN, TRUE, NULL);
15464         } else {
15465           GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
15466               content_encoding);
15467         }
15468       } else {
15469         GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
15470             namespaces);
15471       }
15472
15473       break;
15474     }
15475     default:
15476       break;
15477   }
15478
15479   if (!caps)
15480     caps = _get_unknown_codec_name ("meta", fourcc);
15481
15482   return caps;
15483 }
15484
15485 static GstCaps *
15486 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15487     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15488     const guint8 * stsd_entry_data, gchar ** codec_name)
15489 {
15490   GstCaps *caps;
15491
15492   switch (fourcc) {
15493     case FOURCC_m1v:
15494       _codec ("MPEG 1 video");
15495       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15496           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15497       break;
15498     default:
15499       caps = NULL;
15500       break;
15501   }
15502   return caps;
15503 }
15504
15505 static void
15506 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15507     const gchar * system_id)
15508 {
15509   gint i;
15510
15511   if (!qtdemux->protection_system_ids)
15512     qtdemux->protection_system_ids =
15513         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15514   /* Check whether we already have an entry for this system ID. */
15515   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15516     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15517     if (g_ascii_strcasecmp (system_id, id) == 0) {
15518       return;
15519     }
15520   }
15521   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15522   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15523           -1));
15524 }