00956a6c252e060410ae171fac983397bc53fdbb
[platform/upstream/gstreamer.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @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 "gst/gst-i18n-plugin.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 "qtatomparser.h"
63 #include "qtdemux_types.h"
64 #include "qtdemux_dump.h"
65 #include "fourcc.h"
66 #include "descriptors.h"
67 #include "qtdemux_lang.h"
68 #include "qtdemux.h"
69 #include "qtpalette.h"
70 #include "qtdemux_tags.h"
71 #include "qtdemux_tree.h"
72
73 #include <stdlib.h>
74 #include <string.h>
75
76 #include <math.h>
77 #include <gst/math-compat.h>
78
79 #ifdef HAVE_ZLIB
80 # include <zlib.h>
81 #endif
82
83 /* max. size considered 'sane' for non-mdat atoms */
84 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
85
86 /* if the sample index is larger than this, something is likely wrong */
87 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
88
89 /* For converting qt creation times to unix epoch times */
90 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
91 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
92 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
93     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
94
95 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
96
97 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
98
99 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
100
101 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
102 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
103 #define QTDEMUX_NTH_STREAM(demux,idx) \
104    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
105 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
107
108 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
109
110 GST_DEBUG_CATEGORY (qtdemux_debug);
111 #define GST_CAT_DEFAULT qtdemux_debug
112
113 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
114
115 /* Macros for converting to/from timescale */
116 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
117 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
118
119 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
120 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
121
122 /* timestamp is the DTS */
123 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
124 /* timestamp + offset + cslg_shift is the outgoing PTS */
125 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
126 /* timestamp + offset is the PTS used for internal seek calculations */
127 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
128 /* timestamp + duration - dts is the duration */
129 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
130
131 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
132
133 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
134 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
135     GST_TRACE("Locking from thread %p", g_thread_self()); \
136     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
137     GST_TRACE("Locked from thread %p", g_thread_self()); \
138  } G_STMT_END
139
140 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
141     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
142     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
143  } G_STMT_END
144
145 /*
146  * Quicktime has tracks and segments. A track is a continuous piece of
147  * multimedia content. The track is not always played from start to finish but
148  * instead, pieces of the track are 'cut out' and played in sequence. This is
149  * what the segments do.
150  *
151  * Inside the track we have keyframes (K) and delta frames. The track has its
152  * own timing, which starts from 0 and extends to end. The position in the track
153  * is called the media_time.
154  *
155  * The segments now describe the pieces that should be played from this track
156  * and are basically tuples of media_time/duration/rate entries. We can have
157  * multiple segments and they are all played after one another. An example:
158  *
159  * segment 1: media_time: 1 second, duration: 1 second, rate 1
160  * segment 2: media_time: 3 second, duration: 2 second, rate 2
161  *
162  * To correctly play back this track, one must play: 1 second of media starting
163  * from media_time 1 followed by 2 seconds of media starting from media_time 3
164  * at a rate of 2.
165  *
166  * Each of the segments will be played at a specific time, the first segment at
167  * time 0, the second one after the duration of the first one, etc.. Note that
168  * the time in resulting playback is not identical to the media_time of the
169  * track anymore.
170  *
171  * Visually, assuming the track has 4 second of media_time:
172  *
173  *                (a)                   (b)          (c)              (d)
174  *         .-----------------------------------------------------------.
175  * track:  | K.....K.........K........K.......K.......K...........K... |
176  *         '-----------------------------------------------------------'
177  *         0              1              2              3              4
178  *           .------------^              ^   .----------^              ^
179  *          /              .-------------'  /       .------------------'
180  *         /              /          .-----'       /
181  *         .--------------.         .--------------.
182  *         | segment 1    |         | segment 2    |
183  *         '--------------'         '--------------'
184  *
185  * The challenge here is to cut out the right pieces of the track for each of
186  * the playback segments. This fortunately can easily be done with the SEGMENT
187  * events of GStreamer.
188  *
189  * For playback of segment 1, we need to provide the decoder with the keyframe
190  * (a), in the above figure, but we must instruct it only to output the decoded
191  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
192  * position set to the time of the segment: 0.
193  *
194  * We then proceed to push data from keyframe (a) to frame (b). The decoder
195  * decodes but clips all before media_time 1.
196  *
197  * After finishing a segment, we push out a new SEGMENT event with the clipping
198  * boundaries of the new data.
199  *
200  * This is a good usecase for the GStreamer accumulated SEGMENT events.
201  */
202
203 struct _QtDemuxSegment
204 {
205   /* global time and duration, all gst time */
206   GstClockTime time;
207   GstClockTime stop_time;
208   GstClockTime duration;
209   /* media time of trak, all gst time */
210   GstClockTime media_start;
211   GstClockTime media_stop;
212   gdouble rate;
213   /* Media start time in trak timescale units */
214   guint32 trak_media_start;
215 };
216
217 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
218
219 /* Used with fragmented MP4 files (mfra atom) */
220 struct _QtDemuxRandomAccessEntry
221 {
222   GstClockTime ts;
223   guint64 moof_offset;
224 };
225
226
227 /* Contains properties and cryptographic info for a set of samples from a
228  * track protected using Common Encryption (cenc) */
229 struct _QtDemuxCencSampleSetInfo
230 {
231   GstStructure *default_properties;
232
233   /* @crypto_info holds one GstStructure per sample */
234   GPtrArray *crypto_info;
235 };
236
237 static const gchar *
238 qt_demux_state_string (enum QtDemuxState state)
239 {
240   switch (state) {
241     case QTDEMUX_STATE_INITIAL:
242       return "<INITIAL>";
243     case QTDEMUX_STATE_HEADER:
244       return "<HEADER>";
245     case QTDEMUX_STATE_MOVIE:
246       return "<MOVIE>";
247     case QTDEMUX_STATE_BUFFER_MDAT:
248       return "<BUFFER_MDAT>";
249     default:
250       return "<UNKNOWN>";
251   }
252 }
253
254 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
255
256 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
257
258 static GstStaticPadTemplate gst_qtdemux_sink_template =
259     GST_STATIC_PAD_TEMPLATE ("sink",
260     GST_PAD_SINK,
261     GST_PAD_ALWAYS,
262     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
263         "application/x-3gp")
264     );
265
266 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
267 GST_STATIC_PAD_TEMPLATE ("video_%u",
268     GST_PAD_SRC,
269     GST_PAD_SOMETIMES,
270     GST_STATIC_CAPS_ANY);
271
272 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
273 GST_STATIC_PAD_TEMPLATE ("audio_%u",
274     GST_PAD_SRC,
275     GST_PAD_SOMETIMES,
276     GST_STATIC_CAPS_ANY);
277
278 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
279 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
280     GST_PAD_SRC,
281     GST_PAD_SOMETIMES,
282     GST_STATIC_CAPS_ANY);
283
284 #define gst_qtdemux_parent_class parent_class
285 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
286
287 static void gst_qtdemux_dispose (GObject * object);
288 static void gst_qtdemux_finalize (GObject * object);
289
290 static guint32
291 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
292     GstClockTime media_time);
293 static guint32
294 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
295     QtDemuxStream * str, gint64 media_offset);
296
297 #if 0
298 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
299 static GstIndex *gst_qtdemux_get_index (GstElement * element);
300 #endif
301 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
302     GstStateChange transition);
303 static void gst_qtdemux_set_context (GstElement * element,
304     GstContext * context);
305 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
306 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
307     GstObject * parent, GstPadMode mode, gboolean active);
308
309 static void gst_qtdemux_loop (GstPad * pad);
310 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
311     GstBuffer * inbuf);
312 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
313     GstEvent * event);
314 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
315     GstQuery * query);
316 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
317 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
318     QtDemuxStream * stream);
319 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
320     QtDemuxStream * stream);
321 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
322     gboolean force);
323
324 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
325
326 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
327     const guint8 * buffer, guint length);
328 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
329     const guint8 * buffer, guint length);
330 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
331
332 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
333     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
334     GstTagList * list);
335 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
336     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
337     const guint8 * stsd_entry_data, gchar ** codec_name);
338 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
339     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
340     const guint8 * data, int len, gchar ** codec_name);
341 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
342     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
343     gchar ** codec_name);
344 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
345     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
346     const guint8 * stsd_entry_data, gchar ** codec_name);
347
348 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, guint32 n);
350 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
351 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
352 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
353 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
354 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
355 static void qtdemux_do_allocation (QtDemuxStream * stream,
356     GstQTDemux * qtdemux);
357 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
358     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
359 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
360     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
361     GstClockTime * _start, GstClockTime * _stop);
362 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
363     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
364
365 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
366 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
367
368 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
369
370 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
371     QtDemuxStream * stream, guint sample_index);
372 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
373     const gchar * id);
374 static void qtdemux_gst_structure_free (GstStructure * gststructure);
375 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
376
377 static void
378 gst_qtdemux_class_init (GstQTDemuxClass * klass)
379 {
380   GObjectClass *gobject_class;
381   GstElementClass *gstelement_class;
382
383   gobject_class = (GObjectClass *) klass;
384   gstelement_class = (GstElementClass *) klass;
385
386   parent_class = g_type_class_peek_parent (klass);
387
388   gobject_class->dispose = gst_qtdemux_dispose;
389   gobject_class->finalize = gst_qtdemux_finalize;
390
391   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
392 #if 0
393   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
394   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
395 #endif
396   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
397
398   gst_tag_register_musicbrainz_tags ();
399
400   gst_element_class_add_static_pad_template (gstelement_class,
401       &gst_qtdemux_sink_template);
402   gst_element_class_add_static_pad_template (gstelement_class,
403       &gst_qtdemux_videosrc_template);
404   gst_element_class_add_static_pad_template (gstelement_class,
405       &gst_qtdemux_audiosrc_template);
406   gst_element_class_add_static_pad_template (gstelement_class,
407       &gst_qtdemux_subsrc_template);
408   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
409       "Codec/Demuxer",
410       "Demultiplex a QuickTime file into audio and video streams",
411       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
412
413   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
414   gst_riff_init ();
415 }
416
417 static void
418 gst_qtdemux_init (GstQTDemux * qtdemux)
419 {
420   qtdemux->sinkpad =
421       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
422   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
423   gst_pad_set_activatemode_function (qtdemux->sinkpad,
424       qtdemux_sink_activate_mode);
425   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
426   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
427   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
428   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
429
430   qtdemux->adapter = gst_adapter_new ();
431   g_queue_init (&qtdemux->protection_event_queue);
432   qtdemux->flowcombiner = gst_flow_combiner_new ();
433   g_mutex_init (&qtdemux->expose_lock);
434
435   qtdemux->active_streams = g_ptr_array_new_with_free_func
436       ((GDestroyNotify) gst_qtdemux_stream_unref);
437   qtdemux->old_streams = g_ptr_array_new_with_free_func
438       ((GDestroyNotify) gst_qtdemux_stream_unref);
439
440   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
441
442   gst_qtdemux_reset (qtdemux, TRUE);
443 }
444
445 static void
446 gst_qtdemux_finalize (GObject * object)
447 {
448   GstQTDemux *qtdemux = GST_QTDEMUX (object);
449
450   g_free (qtdemux->redirect_location);
451
452   G_OBJECT_CLASS (parent_class)->finalize (object);
453 }
454
455 static void
456 gst_qtdemux_dispose (GObject * object)
457 {
458   GstQTDemux *qtdemux = GST_QTDEMUX (object);
459
460   if (qtdemux->adapter) {
461     g_object_unref (G_OBJECT (qtdemux->adapter));
462     qtdemux->adapter = NULL;
463   }
464   gst_tag_list_unref (qtdemux->tag_list);
465   gst_flow_combiner_free (qtdemux->flowcombiner);
466   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
467       NULL);
468   g_queue_clear (&qtdemux->protection_event_queue);
469
470   g_free (qtdemux->cenc_aux_info_sizes);
471   qtdemux->cenc_aux_info_sizes = NULL;
472   g_mutex_clear (&qtdemux->expose_lock);
473
474   g_ptr_array_free (qtdemux->active_streams, TRUE);
475   g_ptr_array_free (qtdemux->old_streams, TRUE);
476
477   G_OBJECT_CLASS (parent_class)->dispose (object);
478 }
479
480 static void
481 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
482 {
483   if (qtdemux->redirect_location) {
484     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
485         (_("This file contains no playable streams.")),
486         ("no known streams found, a redirect message has been posted"),
487         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
488   } else {
489     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
490         (_("This file contains no playable streams.")),
491         ("no known streams found"));
492   }
493 }
494
495 static GstBuffer *
496 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
497 {
498   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
499       mem, size, 0, size, mem, free_func);
500 }
501
502 static GstFlowReturn
503 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
504     GstBuffer ** buf)
505 {
506   GstFlowReturn flow;
507   GstMapInfo map;
508   gsize bsize;
509
510   if (G_UNLIKELY (size == 0)) {
511     GstFlowReturn ret;
512     GstBuffer *tmp = NULL;
513
514     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
515     if (ret != GST_FLOW_OK)
516       return ret;
517
518     gst_buffer_map (tmp, &map, GST_MAP_READ);
519     size = QT_UINT32 (map.data);
520     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
521
522     gst_buffer_unmap (tmp, &map);
523     gst_buffer_unref (tmp);
524   }
525
526   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
527   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
528     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
529       /* we're pulling header but already got most interesting bits,
530        * so never mind the rest (e.g. tags) (that much) */
531       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
532           size);
533       return GST_FLOW_EOS;
534     } else {
535       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
536           (_("This file is invalid and cannot be played.")),
537           ("atom has bogus size %" G_GUINT64_FORMAT, size));
538       return GST_FLOW_ERROR;
539     }
540   }
541
542   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
543
544   if (G_UNLIKELY (flow != GST_FLOW_OK))
545     return flow;
546
547   bsize = gst_buffer_get_size (*buf);
548   /* Catch short reads - we don't want any partial atoms */
549   if (G_UNLIKELY (bsize < size)) {
550     GST_WARNING_OBJECT (qtdemux,
551         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
552     gst_buffer_unref (*buf);
553     *buf = NULL;
554     return GST_FLOW_EOS;
555   }
556
557   return flow;
558 }
559
560 #if 1
561 static gboolean
562 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
563     GstFormat src_format, gint64 src_value, GstFormat dest_format,
564     gint64 * dest_value)
565 {
566   gboolean res = TRUE;
567   QtDemuxStream *stream = gst_pad_get_element_private (pad);
568   gint32 index;
569
570   if (stream->subtype != FOURCC_vide) {
571     res = FALSE;
572     goto done;
573   }
574
575   switch (src_format) {
576     case GST_FORMAT_TIME:
577       switch (dest_format) {
578         case GST_FORMAT_BYTES:{
579           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
580           if (-1 == index) {
581             res = FALSE;
582             goto done;
583           }
584
585           *dest_value = stream->samples[index].offset;
586
587           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
588               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
589               GST_TIME_ARGS (src_value), *dest_value);
590           break;
591         }
592         default:
593           res = FALSE;
594           break;
595       }
596       break;
597     case GST_FORMAT_BYTES:
598       switch (dest_format) {
599         case GST_FORMAT_TIME:{
600           index =
601               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
602               stream, src_value);
603
604           if (-1 == index) {
605             res = FALSE;
606             goto done;
607           }
608
609           *dest_value =
610               QTSTREAMTIME_TO_GSTTIME (stream,
611               stream->samples[index].timestamp);
612           GST_DEBUG_OBJECT (qtdemux,
613               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
614               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
615           break;
616         }
617         default:
618           res = FALSE;
619           break;
620       }
621       break;
622     default:
623       res = FALSE;
624       break;
625   }
626
627 done:
628   return res;
629 }
630 #endif
631
632 static gboolean
633 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
634 {
635   gboolean res = FALSE;
636
637   *duration = GST_CLOCK_TIME_NONE;
638
639   if (qtdemux->duration != 0 &&
640       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
641     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
642     res = TRUE;
643   } else {
644     *duration = GST_CLOCK_TIME_NONE;
645   }
646
647   return res;
648 }
649
650 static gboolean
651 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
652     GstQuery * query)
653 {
654   gboolean res = FALSE;
655   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
656
657   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
658
659   switch (GST_QUERY_TYPE (query)) {
660     case GST_QUERY_POSITION:{
661       GstFormat fmt;
662
663       gst_query_parse_position (query, &fmt, NULL);
664       if (fmt == GST_FORMAT_TIME
665           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
666         gst_query_set_position (query, GST_FORMAT_TIME,
667             qtdemux->segment.position);
668         res = TRUE;
669       }
670     }
671       break;
672     case GST_QUERY_DURATION:{
673       GstFormat fmt;
674
675       gst_query_parse_duration (query, &fmt, NULL);
676       if (fmt == GST_FORMAT_TIME) {
677         /* First try to query upstream */
678         res = gst_pad_query_default (pad, parent, query);
679         if (!res) {
680           GstClockTime duration;
681           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
682             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
683             res = TRUE;
684           }
685         }
686       }
687       break;
688     }
689     case GST_QUERY_CONVERT:{
690       GstFormat src_fmt, dest_fmt;
691       gint64 src_value, dest_value = 0;
692
693       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
694
695       res = gst_qtdemux_src_convert (qtdemux, pad,
696           src_fmt, src_value, dest_fmt, &dest_value);
697       if (res)
698         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
699
700       break;
701     }
702     case GST_QUERY_FORMATS:
703       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
704       res = TRUE;
705       break;
706     case GST_QUERY_SEEKING:{
707       GstFormat fmt;
708       gboolean seekable;
709
710       /* try upstream first */
711       res = gst_pad_query_default (pad, parent, query);
712
713       if (!res) {
714         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
715         if (fmt == GST_FORMAT_TIME) {
716           GstClockTime duration;
717
718           gst_qtdemux_get_duration (qtdemux, &duration);
719           seekable = TRUE;
720           if (!qtdemux->pullbased) {
721             GstQuery *q;
722
723             /* we might be able with help from upstream */
724             seekable = FALSE;
725             q = gst_query_new_seeking (GST_FORMAT_BYTES);
726             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
727               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
728               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
729             }
730             gst_query_unref (q);
731           }
732           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
733           res = TRUE;
734         }
735       }
736       break;
737     }
738     case GST_QUERY_SEGMENT:
739     {
740       GstFormat format;
741       gint64 start, stop;
742
743       format = qtdemux->segment.format;
744
745       start =
746           gst_segment_to_stream_time (&qtdemux->segment, format,
747           qtdemux->segment.start);
748       if ((stop = qtdemux->segment.stop) == -1)
749         stop = qtdemux->segment.duration;
750       else
751         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
752
753       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
754       res = TRUE;
755       break;
756     }
757     default:
758       res = gst_pad_query_default (pad, parent, query);
759       break;
760   }
761
762   return res;
763 }
764
765 static void
766 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
767 {
768   if (G_LIKELY (stream->pad)) {
769     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
770         GST_DEBUG_PAD_NAME (stream->pad));
771
772     if (!gst_tag_list_is_empty (stream->stream_tags)) {
773       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
774           stream->stream_tags);
775       gst_pad_push_event (stream->pad,
776           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
777     }
778
779     if (G_UNLIKELY (stream->send_global_tags)) {
780       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
781           qtdemux->tag_list);
782       gst_pad_push_event (stream->pad,
783           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
784       stream->send_global_tags = FALSE;
785     }
786   }
787 }
788
789 /* push event on all source pads; takes ownership of the event */
790 static void
791 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
792 {
793   gboolean has_valid_stream = FALSE;
794   GstEventType etype = GST_EVENT_TYPE (event);
795   guint i;
796
797   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
798       GST_EVENT_TYPE_NAME (event));
799
800   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
801     GstPad *pad;
802     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
803     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
804
805     if ((pad = stream->pad)) {
806       has_valid_stream = TRUE;
807
808       if (etype == GST_EVENT_EOS) {
809         /* let's not send twice */
810         if (stream->sent_eos)
811           continue;
812         stream->sent_eos = TRUE;
813       }
814
815       gst_pad_push_event (pad, gst_event_ref (event));
816     }
817   }
818
819   gst_event_unref (event);
820
821   /* if it is EOS and there are no pads, post an error */
822   if (!has_valid_stream && etype == GST_EVENT_EOS) {
823     gst_qtdemux_post_no_playable_stream_error (qtdemux);
824   }
825 }
826
827 typedef struct
828 {
829   guint64 media_time;
830 } FindData;
831
832 static gint
833 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
834 {
835   if ((gint64) s1->timestamp > *media_time)
836     return 1;
837   if ((gint64) s1->timestamp == *media_time)
838     return 0;
839
840   return -1;
841 }
842
843 /* find the index of the sample that includes the data for @media_time using a
844  * binary search.  Only to be called in optimized cases of linear search below.
845  *
846  * Returns the index of the sample with the corresponding *DTS*.
847  */
848 static guint32
849 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
850     guint64 media_time)
851 {
852   QtDemuxSample *result;
853   guint32 index;
854
855   /* convert media_time to mov format */
856   media_time =
857       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
858
859   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
860       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
861       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
862
863   if (G_LIKELY (result))
864     index = result - str->samples;
865   else
866     index = 0;
867
868   return index;
869 }
870
871
872
873 /* find the index of the sample that includes the data for @media_offset using a
874  * linear search
875  *
876  * Returns the index of the sample.
877  */
878 static guint32
879 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
880     QtDemuxStream * str, gint64 media_offset)
881 {
882   QtDemuxSample *result = str->samples;
883   guint32 index = 0;
884
885   if (result == NULL || str->n_samples == 0)
886     return -1;
887
888   if (media_offset == result->offset)
889     return index;
890
891   result++;
892   while (index < str->n_samples - 1) {
893     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
894       goto parse_failed;
895
896     if (media_offset < result->offset)
897       break;
898
899     index++;
900     result++;
901   }
902   return index;
903
904   /* ERRORS */
905 parse_failed:
906   {
907     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
908     return -1;
909   }
910 }
911
912 /* find the index of the sample that includes the data for @media_time using a
913  * linear search, and keeping in mind that not all samples may have been parsed
914  * yet.  If possible, it will delegate to binary search.
915  *
916  * Returns the index of the sample.
917  */
918 static guint32
919 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
920     GstClockTime media_time)
921 {
922   guint32 index = 0;
923   guint64 mov_time;
924   QtDemuxSample *sample;
925
926   /* convert media_time to mov format */
927   mov_time =
928       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
929
930   sample = str->samples;
931   if (mov_time == sample->timestamp + sample->pts_offset)
932     return index;
933
934   /* use faster search if requested time in already parsed range */
935   sample = str->samples + str->stbl_index;
936   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
937     index = gst_qtdemux_find_index (qtdemux, str, media_time);
938     sample = str->samples + index;
939   } else {
940     while (index < str->n_samples - 1) {
941       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
942         goto parse_failed;
943
944       sample = str->samples + index + 1;
945       if (mov_time < sample->timestamp) {
946         sample = str->samples + index;
947         break;
948       }
949
950       index++;
951     }
952   }
953
954   /* sample->timestamp is now <= media_time, need to find the corresponding
955    * PTS now by looking backwards */
956   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
957     index--;
958     sample = str->samples + index;
959   }
960
961   return index;
962
963   /* ERRORS */
964 parse_failed:
965   {
966     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
967     return -1;
968   }
969 }
970
971 /* find the index of the keyframe needed to decode the sample at @index
972  * of stream @str, or of a subsequent keyframe (depending on @next)
973  *
974  * Returns the index of the keyframe.
975  */
976 static guint32
977 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
978     guint32 index, gboolean next)
979 {
980   guint32 new_index = index;
981
982   if (index >= str->n_samples) {
983     new_index = str->n_samples;
984     goto beach;
985   }
986
987   /* all keyframes, return index */
988   if (str->all_keyframe) {
989     new_index = index;
990     goto beach;
991   }
992
993   /* else search until we have a keyframe */
994   while (new_index < str->n_samples) {
995     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
996       goto parse_failed;
997
998     if (str->samples[new_index].keyframe)
999       break;
1000
1001     if (new_index == 0)
1002       break;
1003
1004     if (next)
1005       new_index++;
1006     else
1007       new_index--;
1008   }
1009
1010   if (new_index == str->n_samples) {
1011     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1012     new_index = -1;
1013   }
1014
1015 beach:
1016   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1017       "gave %u", next ? "after" : "before", index, new_index);
1018
1019   return new_index;
1020
1021   /* ERRORS */
1022 parse_failed:
1023   {
1024     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1025     return -1;
1026   }
1027 }
1028
1029 /* find the segment for @time_position for @stream
1030  *
1031  * Returns the index of the segment containing @time_position.
1032  * Returns the last segment and sets the @eos variable to TRUE
1033  * if the time is beyond the end. @eos may be NULL
1034  */
1035 static guint32
1036 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1037     GstClockTime time_position)
1038 {
1039   gint i;
1040   guint32 seg_idx;
1041
1042   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1043       GST_TIME_ARGS (time_position));
1044
1045   seg_idx = -1;
1046   for (i = 0; i < stream->n_segments; i++) {
1047     QtDemuxSegment *segment = &stream->segments[i];
1048
1049     GST_LOG_OBJECT (stream->pad,
1050         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1051         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1052
1053     /* For the last segment we include stop_time in the last segment */
1054     if (i < stream->n_segments - 1) {
1055       if (segment->time <= time_position && time_position < segment->stop_time) {
1056         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1057         seg_idx = i;
1058         break;
1059       }
1060     } else {
1061       /* Last segment always matches */
1062       seg_idx = i;
1063       break;
1064     }
1065   }
1066   return seg_idx;
1067 }
1068
1069 /* move the stream @str to the sample position @index.
1070  *
1071  * Updates @str->sample_index and marks discontinuity if needed.
1072  */
1073 static void
1074 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1075     guint32 index)
1076 {
1077   /* no change needed */
1078   if (index == str->sample_index)
1079     return;
1080
1081   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1082       str->n_samples);
1083
1084   /* position changed, we have a discont */
1085   str->sample_index = index;
1086   str->offset_in_sample = 0;
1087   /* Each time we move in the stream we store the position where we are
1088    * starting from */
1089   str->from_sample = index;
1090   str->discont = TRUE;
1091 }
1092
1093 static void
1094 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1095     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1096 {
1097   guint64 min_offset;
1098   gint64 min_byte_offset = -1;
1099   guint i;
1100
1101   min_offset = desired_time;
1102
1103   /* for each stream, find the index of the sample in the segment
1104    * and move back to the previous keyframe. */
1105   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1106     QtDemuxStream *str;
1107     guint32 index, kindex;
1108     guint32 seg_idx;
1109     GstClockTime media_start;
1110     GstClockTime media_time;
1111     GstClockTime seg_time;
1112     QtDemuxSegment *seg;
1113     gboolean empty_segment = FALSE;
1114
1115     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1116
1117     if (CUR_STREAM (str)->sparse && !use_sparse)
1118       continue;
1119
1120     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1121     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1122
1123     /* get segment and time in the segment */
1124     seg = &str->segments[seg_idx];
1125     seg_time = (desired_time - seg->time) * seg->rate;
1126
1127     while (QTSEGMENT_IS_EMPTY (seg)) {
1128       seg_time = 0;
1129       empty_segment = TRUE;
1130       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1131           seg_idx);
1132       seg_idx++;
1133       if (seg_idx == str->n_segments)
1134         break;
1135       seg = &str->segments[seg_idx];
1136     }
1137
1138     if (seg_idx == str->n_segments) {
1139       /* FIXME track shouldn't have the last segment as empty, but if it
1140        * happens we better handle it */
1141       continue;
1142     }
1143
1144     /* get the media time in the segment */
1145     media_start = seg->media_start + seg_time;
1146
1147     /* get the index of the sample with media time */
1148     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1149     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1150         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1151         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1152         empty_segment);
1153
1154     /* shift to next frame if we are looking for next keyframe */
1155     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1156         && index < str->stbl_index)
1157       index++;
1158
1159     if (!empty_segment) {
1160       /* find previous keyframe */
1161       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1162
1163       /* we will settle for one before if none found after */
1164       if (next && kindex == -1)
1165         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1166
1167       /* Update the requested time whenever a keyframe was found, to make it
1168        * accurate and avoid having the first buffer fall outside of the segment
1169        */
1170       if (kindex != -1) {
1171         index = kindex;
1172
1173         /* get timestamp of keyframe */
1174         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1175         GST_DEBUG_OBJECT (qtdemux,
1176             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1177             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1178             str->samples[kindex].offset);
1179
1180         /* keyframes in the segment get a chance to change the
1181          * desired_offset. keyframes out of the segment are
1182          * ignored. */
1183         if (media_time >= seg->media_start) {
1184           GstClockTime seg_time;
1185
1186           /* this keyframe is inside the segment, convert back to
1187            * segment time */
1188           seg_time = (media_time - seg->media_start) + seg->time;
1189           if ((!next && (seg_time < min_offset)) ||
1190               (next && (seg_time > min_offset)))
1191             min_offset = seg_time;
1192         }
1193       }
1194     }
1195
1196     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1197       min_byte_offset = str->samples[index].offset;
1198   }
1199
1200   if (key_time)
1201     *key_time = min_offset;
1202   if (key_offset)
1203     *key_offset = min_byte_offset;
1204 }
1205
1206 static gboolean
1207 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1208     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1209 {
1210   gboolean res;
1211
1212   g_return_val_if_fail (format != NULL, FALSE);
1213   g_return_val_if_fail (cur != NULL, FALSE);
1214   g_return_val_if_fail (stop != NULL, FALSE);
1215
1216   if (*format == GST_FORMAT_TIME)
1217     return TRUE;
1218
1219   res = TRUE;
1220   if (cur_type != GST_SEEK_TYPE_NONE)
1221     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1222   if (res && stop_type != GST_SEEK_TYPE_NONE)
1223     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1224
1225   if (res)
1226     *format = GST_FORMAT_TIME;
1227
1228   return res;
1229 }
1230
1231 /* perform seek in push based mode:
1232    find BYTE position to move to based on time and delegate to upstream
1233 */
1234 static gboolean
1235 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1236 {
1237   gdouble rate;
1238   GstFormat format;
1239   GstSeekFlags flags;
1240   GstSeekType cur_type, stop_type;
1241   gint64 cur, stop, key_cur;
1242   gboolean res;
1243   gint64 byte_cur;
1244   gint64 original_stop;
1245   guint32 seqnum;
1246
1247   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1248
1249   gst_event_parse_seek (event, &rate, &format, &flags,
1250       &cur_type, &cur, &stop_type, &stop);
1251   seqnum = gst_event_get_seqnum (event);
1252
1253   /* Directly send the instant-rate-change event here before taking the
1254    * stream-lock so that it can be applied as soon as possible */
1255   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1256     GstEvent *ev;
1257
1258     /* instant rate change only supported if direction does not change. All
1259      * other requirements are already checked before creating the seek event
1260      * but let's double-check here to be sure */
1261     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1262         (qtdemux->segment.rate < 0 && rate > 0) ||
1263         cur_type != GST_SEEK_TYPE_NONE ||
1264         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1265       GST_ERROR_OBJECT (qtdemux,
1266           "Instant rate change seeks only supported in the "
1267           "same direction, without flushing and position change");
1268       return FALSE;
1269     }
1270
1271     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1272         (GstSegmentFlags) flags);
1273     gst_event_set_seqnum (ev, seqnum);
1274     gst_qtdemux_push_event (qtdemux, ev);
1275     return TRUE;
1276   }
1277
1278   /* only forward streaming and seeking is possible */
1279   if (rate <= 0)
1280     goto unsupported_seek;
1281
1282   /* convert to TIME if needed and possible */
1283   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1284           stop_type, &stop))
1285     goto no_format;
1286
1287   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1288    * the original stop position to use when upstream pushes the new segment
1289    * for this seek */
1290   original_stop = stop;
1291   stop = -1;
1292
1293   /* find reasonable corresponding BYTE position,
1294    * also try to mind about keyframes, since we can not go back a bit for them
1295    * later on */
1296   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1297    * mostly just work, but let's not yet boldly go there  ... */
1298   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1299
1300   if (byte_cur == -1)
1301     goto abort_seek;
1302
1303   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1304       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1305       stop);
1306
1307   GST_OBJECT_LOCK (qtdemux);
1308   qtdemux->seek_offset = byte_cur;
1309   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1310     qtdemux->push_seek_start = cur;
1311   } else {
1312     qtdemux->push_seek_start = key_cur;
1313   }
1314
1315   if (stop_type == GST_SEEK_TYPE_NONE) {
1316     qtdemux->push_seek_stop = qtdemux->segment.stop;
1317   } else {
1318     qtdemux->push_seek_stop = original_stop;
1319   }
1320   GST_OBJECT_UNLOCK (qtdemux);
1321
1322   qtdemux->segment_seqnum = seqnum;
1323   /* BYTE seek event */
1324   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1325       stop_type, stop);
1326   gst_event_set_seqnum (event, seqnum);
1327   res = gst_pad_push_event (qtdemux->sinkpad, event);
1328
1329   return res;
1330
1331   /* ERRORS */
1332 abort_seek:
1333   {
1334     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1335         "seek aborted.");
1336     return FALSE;
1337   }
1338 unsupported_seek:
1339   {
1340     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1341     return FALSE;
1342   }
1343 no_format:
1344   {
1345     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1346     return FALSE;
1347   }
1348 }
1349
1350 /* perform the seek.
1351  *
1352  * We set all segment_indexes in the streams to unknown and
1353  * adjust the time_position to the desired position. this is enough
1354  * to trigger a segment switch in the streaming thread to start
1355  * streaming from the desired position.
1356  *
1357  * Keyframe seeking is a little more complicated when dealing with
1358  * segments. Ideally we want to move to the previous keyframe in
1359  * the segment but there might not be a keyframe in the segment. In
1360  * fact, none of the segments could contain a keyframe. We take a
1361  * practical approach: seek to the previous keyframe in the segment,
1362  * if there is none, seek to the beginning of the segment.
1363  *
1364  * Called with STREAM_LOCK
1365  */
1366 static gboolean
1367 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1368     guint32 seqnum, GstSeekFlags flags)
1369 {
1370   gint64 desired_offset;
1371   guint i;
1372
1373   desired_offset = segment->position;
1374
1375   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1376       GST_TIME_ARGS (desired_offset));
1377
1378   /* may not have enough fragmented info to do this adjustment,
1379    * and we can't scan (and probably should not) at this time with
1380    * possibly flushing upstream */
1381   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1382     gint64 min_offset;
1383     gboolean next, before, after;
1384
1385     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1386     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1387     next = after && !before;
1388     if (segment->rate < 0)
1389       next = !next;
1390
1391     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1392         NULL);
1393     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1394         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1395     desired_offset = min_offset;
1396   }
1397
1398   /* and set all streams to the final position */
1399   GST_OBJECT_LOCK (qtdemux);
1400   gst_flow_combiner_reset (qtdemux->flowcombiner);
1401   GST_OBJECT_UNLOCK (qtdemux);
1402   qtdemux->segment_seqnum = seqnum;
1403   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1404     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1405
1406     stream->time_position = desired_offset;
1407     stream->accumulated_base = 0;
1408     stream->sample_index = -1;
1409     stream->offset_in_sample = 0;
1410     stream->segment_index = -1;
1411     stream->sent_eos = FALSE;
1412     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1413
1414     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1415       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1416   }
1417   segment->position = desired_offset;
1418   if (segment->rate >= 0) {
1419     segment->start = desired_offset;
1420     /* We need to update time as we update start in that direction */
1421     segment->time = desired_offset;
1422
1423     /* we stop at the end */
1424     if (segment->stop == -1)
1425       segment->stop = segment->duration;
1426   } else {
1427     segment->stop = desired_offset;
1428   }
1429
1430   if (qtdemux->fragmented)
1431     qtdemux->fragmented_seek_pending = TRUE;
1432
1433   return TRUE;
1434 }
1435
1436 /* do a seek in pull based mode */
1437 static gboolean
1438 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1439 {
1440   gdouble rate = 1.0;
1441   GstFormat format;
1442   GstSeekFlags flags;
1443   GstSeekType cur_type, stop_type;
1444   gint64 cur, stop;
1445   gboolean flush, instant_rate_change;
1446   gboolean update;
1447   GstSegment seeksegment;
1448   guint32 seqnum = GST_SEQNUM_INVALID;
1449   GstEvent *flush_event;
1450   gboolean ret;
1451
1452   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1453
1454   gst_event_parse_seek (event, &rate, &format, &flags,
1455       &cur_type, &cur, &stop_type, &stop);
1456   seqnum = gst_event_get_seqnum (event);
1457
1458   /* we have to have a format as the segment format. Try to convert
1459    * if not. */
1460   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1461           stop_type, &stop))
1462     goto no_format;
1463
1464   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1465
1466   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1467   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1468
1469   /* Directly send the instant-rate-change event here before taking the
1470    * stream-lock so that it can be applied as soon as possible */
1471   if (instant_rate_change) {
1472     GstEvent *ev;
1473
1474     /* instant rate change only supported if direction does not change. All
1475      * other requirements are already checked before creating the seek event
1476      * but let's double-check here to be sure */
1477     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1478         (qtdemux->segment.rate < 0 && rate > 0) ||
1479         cur_type != GST_SEEK_TYPE_NONE ||
1480         stop_type != GST_SEEK_TYPE_NONE || flush) {
1481       GST_ERROR_OBJECT (qtdemux,
1482           "Instant rate change seeks only supported in the "
1483           "same direction, without flushing and position change");
1484       return FALSE;
1485     }
1486
1487     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1488         (GstSegmentFlags) flags);
1489     gst_event_set_seqnum (ev, seqnum);
1490     gst_qtdemux_push_event (qtdemux, ev);
1491     return TRUE;
1492   }
1493
1494   /* stop streaming, either by flushing or by pausing the task */
1495   if (flush) {
1496     flush_event = gst_event_new_flush_start ();
1497     if (seqnum != GST_SEQNUM_INVALID)
1498       gst_event_set_seqnum (flush_event, seqnum);
1499     /* unlock upstream pull_range */
1500     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1501     /* make sure out loop function exits */
1502     gst_qtdemux_push_event (qtdemux, flush_event);
1503   } else {
1504     /* non flushing seek, pause the task */
1505     gst_pad_pause_task (qtdemux->sinkpad);
1506   }
1507
1508   /* wait for streaming to finish */
1509   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1510
1511   /* copy segment, we need this because we still need the old
1512    * segment when we close the current segment. */
1513   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1514
1515   /* configure the segment with the seek variables */
1516   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1517   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1518           cur_type, cur, stop_type, stop, &update)) {
1519     ret = FALSE;
1520     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1521   } else {
1522     /* now do the seek */
1523     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1524   }
1525
1526   /* prepare for streaming again */
1527   if (flush) {
1528     flush_event = gst_event_new_flush_stop (TRUE);
1529     if (seqnum != GST_SEQNUM_INVALID)
1530       gst_event_set_seqnum (flush_event, seqnum);
1531
1532     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1533     gst_qtdemux_push_event (qtdemux, flush_event);
1534   }
1535
1536   /* commit the new segment */
1537   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1538
1539   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1540     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1541         qtdemux->segment.format, qtdemux->segment.position);
1542     if (seqnum != GST_SEQNUM_INVALID)
1543       gst_message_set_seqnum (msg, seqnum);
1544     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1545   }
1546
1547   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1548   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1549       qtdemux->sinkpad, NULL);
1550
1551   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1552
1553   return ret;
1554
1555   /* ERRORS */
1556 no_format:
1557   {
1558     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1559     return FALSE;
1560   }
1561 }
1562
1563 static gboolean
1564 qtdemux_ensure_index (GstQTDemux * qtdemux)
1565 {
1566   guint i;
1567
1568   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1569
1570   /* Build complete index */
1571   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1572     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1573
1574     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1575       GST_LOG_OBJECT (qtdemux,
1576           "Building complete index of track-id %u for seeking failed!",
1577           stream->track_id);
1578       return FALSE;
1579     }
1580   }
1581
1582   return TRUE;
1583 }
1584
1585 static gboolean
1586 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1587     GstEvent * event)
1588 {
1589   gboolean res = TRUE;
1590   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1591
1592   switch (GST_EVENT_TYPE (event)) {
1593     case GST_EVENT_RECONFIGURE:
1594       GST_OBJECT_LOCK (qtdemux);
1595       gst_flow_combiner_reset (qtdemux->flowcombiner);
1596       GST_OBJECT_UNLOCK (qtdemux);
1597       res = gst_pad_event_default (pad, parent, event);
1598       break;
1599     case GST_EVENT_SEEK:
1600     {
1601       GstSeekFlags flags = 0;
1602       gboolean instant_rate_change;
1603
1604 #ifndef GST_DISABLE_GST_DEBUG
1605       GstClockTime ts = gst_util_get_timestamp ();
1606 #endif
1607       guint32 seqnum = gst_event_get_seqnum (event);
1608
1609       qtdemux->received_seek = TRUE;
1610
1611       gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL);
1612       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1613
1614       if (seqnum == qtdemux->segment_seqnum) {
1615         GST_LOG_OBJECT (pad,
1616             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1617         gst_event_unref (event);
1618         return TRUE;
1619       }
1620
1621       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1622         /* seek should be handled by upstream, we might need to re-download fragments */
1623         GST_DEBUG_OBJECT (qtdemux,
1624             "let upstream handle seek for fragmented playback");
1625         goto upstream;
1626       }
1627
1628       gst_event_parse_seek_trickmode_interval (event,
1629           &qtdemux->trickmode_interval);
1630
1631       /* Build complete index for seeking;
1632        * if not a fragmented file at least and we're really doing a seek,
1633        * not just an instant-rate-change */
1634       if (!qtdemux->fragmented && !instant_rate_change) {
1635         if (!qtdemux_ensure_index (qtdemux))
1636           goto index_failed;
1637       }
1638 #ifndef GST_DISABLE_GST_DEBUG
1639       ts = gst_util_get_timestamp () - ts;
1640       GST_INFO_OBJECT (qtdemux,
1641           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1642 #endif
1643       if (qtdemux->pullbased) {
1644         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1645       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1646         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1647         res = TRUE;
1648       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1649           && QTDEMUX_N_STREAMS (qtdemux)
1650           && !qtdemux->fragmented) {
1651         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1652       } else {
1653         GST_DEBUG_OBJECT (qtdemux,
1654             "ignoring seek in push mode in current state");
1655         res = FALSE;
1656       }
1657       gst_event_unref (event);
1658     }
1659       break;
1660     default:
1661     upstream:
1662       res = gst_pad_event_default (pad, parent, event);
1663       break;
1664   }
1665
1666 done:
1667   return res;
1668
1669   /* ERRORS */
1670 index_failed:
1671   {
1672     GST_ERROR_OBJECT (qtdemux, "Index failed");
1673     gst_event_unref (event);
1674     res = FALSE;
1675     goto done;
1676   }
1677 }
1678
1679 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1680  *
1681  * If @fw is false, the coding order is explored backwards.
1682  *
1683  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1684  * sample is found for that track.
1685  *
1686  * The stream and sample index of the sample with the minimum offset in the direction explored
1687  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1688  *
1689  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1690  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1691  * @_stream and @_index. */
1692 static void
1693 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1694     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1695 {
1696   gint i, index;
1697   gint64 time, min_time;
1698   QtDemuxStream *stream;
1699   gint iter;
1700
1701   min_time = -1;
1702   stream = NULL;
1703   index = -1;
1704
1705   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1706     QtDemuxStream *str;
1707     gint inc;
1708     gboolean set_sample;
1709
1710     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1711     set_sample = !set;
1712
1713     if (fw) {
1714       i = 0;
1715       inc = 1;
1716     } else {
1717       i = str->n_samples - 1;
1718       inc = -1;
1719     }
1720
1721     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1722       if (str->samples[i].size == 0)
1723         continue;
1724
1725       if (fw && (str->samples[i].offset < byte_pos))
1726         continue;
1727
1728       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1729         continue;
1730
1731       /* move stream to first available sample */
1732       if (set) {
1733         gst_qtdemux_move_stream (qtdemux, str, i);
1734         set_sample = TRUE;
1735       }
1736
1737       /* avoid index from sparse streams since they might be far away */
1738       if (!CUR_STREAM (str)->sparse) {
1739         /* determine min/max time */
1740         time = QTSAMPLE_PTS (str, &str->samples[i]);
1741         if (min_time == -1 || (!fw && time > min_time) ||
1742             (fw && time < min_time)) {
1743           min_time = time;
1744         }
1745
1746         /* determine stream with leading sample, to get its position */
1747         if (!stream ||
1748             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1749             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1750           stream = str;
1751           index = i;
1752         }
1753       }
1754       break;
1755     }
1756
1757     /* no sample for this stream, mark eos */
1758     if (!set_sample)
1759       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1760   }
1761
1762   if (_time)
1763     *_time = min_time;
1764   if (_stream)
1765     *_stream = stream;
1766   if (_index)
1767     *_index = index;
1768 }
1769
1770 /* Copied from mpegtsbase code */
1771 /* FIXME: replace this function when we add new util function for stream-id creation */
1772 static gchar *
1773 _get_upstream_id (GstQTDemux * demux)
1774 {
1775   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1776
1777   if (!upstream_id) {
1778     /* Try to create one from the upstream URI, else use a randome number */
1779     GstQuery *query;
1780     gchar *uri = NULL;
1781
1782     /* Try to generate one from the URI query and
1783      * if it fails take a random number instead */
1784     query = gst_query_new_uri ();
1785     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1786       gst_query_parse_uri (query, &uri);
1787     }
1788
1789     if (uri) {
1790       GChecksum *cs;
1791
1792       /* And then generate an SHA256 sum of the URI */
1793       cs = g_checksum_new (G_CHECKSUM_SHA256);
1794       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1795       g_free (uri);
1796       upstream_id = g_strdup (g_checksum_get_string (cs));
1797       g_checksum_free (cs);
1798     } else {
1799       /* Just get some random number if the URI query fails */
1800       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1801           "implementing a deterministic way of creating a stream-id");
1802       upstream_id =
1803           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1804           g_random_int (), g_random_int ());
1805     }
1806
1807     gst_query_unref (query);
1808   }
1809   return upstream_id;
1810 }
1811
1812 static QtDemuxStream *
1813 _create_stream (GstQTDemux * demux, guint32 track_id)
1814 {
1815   QtDemuxStream *stream;
1816   gchar *upstream_id;
1817
1818   stream = g_new0 (QtDemuxStream, 1);
1819   stream->demux = demux;
1820   stream->track_id = track_id;
1821   upstream_id = _get_upstream_id (demux);
1822   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1823   g_free (upstream_id);
1824   /* new streams always need a discont */
1825   stream->discont = TRUE;
1826   /* we enable clipping for raw audio/video streams */
1827   stream->need_clip = FALSE;
1828   stream->need_process = FALSE;
1829   stream->segment_index = -1;
1830   stream->time_position = 0;
1831   stream->sample_index = -1;
1832   stream->offset_in_sample = 0;
1833   stream->new_stream = TRUE;
1834   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1835   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1836   stream->protected = FALSE;
1837   stream->protection_scheme_type = 0;
1838   stream->protection_scheme_version = 0;
1839   stream->protection_scheme_info = NULL;
1840   stream->n_samples_moof = 0;
1841   stream->duration_moof = 0;
1842   stream->duration_last_moof = 0;
1843   stream->alignment = 1;
1844   stream->stream_tags = gst_tag_list_new_empty ();
1845   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1846   g_queue_init (&stream->protection_scheme_event_queue);
1847   stream->ref_count = 1;
1848   /* consistent default for push based mode */
1849   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1850   return stream;
1851 }
1852
1853 static gboolean
1854 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1855 {
1856   GstStructure *structure;
1857   const gchar *variant;
1858   const GstCaps *mediacaps = NULL;
1859
1860   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1861
1862   structure = gst_caps_get_structure (caps, 0);
1863   variant = gst_structure_get_string (structure, "variant");
1864
1865   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1866     QtDemuxStream *stream;
1867     const GValue *value;
1868
1869     demux->fragmented = TRUE;
1870     demux->mss_mode = TRUE;
1871
1872     if (QTDEMUX_N_STREAMS (demux) > 1) {
1873       /* can't do this, we can only renegotiate for another mss format */
1874       return FALSE;
1875     }
1876
1877     value = gst_structure_get_value (structure, "media-caps");
1878     /* create stream */
1879     if (value) {
1880       const GValue *timescale_v;
1881
1882       /* TODO update when stream changes during playback */
1883
1884       if (QTDEMUX_N_STREAMS (demux) == 0) {
1885         stream = _create_stream (demux, 1);
1886         g_ptr_array_add (demux->active_streams, stream);
1887         /* mss has no stsd/stsd entry, use id 0 as default */
1888         stream->stsd_entries_length = 1;
1889         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1890         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1891       } else {
1892         stream = QTDEMUX_NTH_STREAM (demux, 0);
1893       }
1894
1895       timescale_v = gst_structure_get_value (structure, "timescale");
1896       if (timescale_v) {
1897         stream->timescale = g_value_get_uint64 (timescale_v);
1898       } else {
1899         /* default mss timescale */
1900         stream->timescale = 10000000;
1901       }
1902       demux->timescale = stream->timescale;
1903
1904       mediacaps = gst_value_get_caps (value);
1905       if (!CUR_STREAM (stream)->caps
1906           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1907         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1908             mediacaps);
1909         stream->new_caps = TRUE;
1910       }
1911       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1912       structure = gst_caps_get_structure (mediacaps, 0);
1913       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1914         stream->subtype = FOURCC_vide;
1915
1916         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1917         gst_structure_get_int (structure, "height",
1918             &CUR_STREAM (stream)->height);
1919         gst_structure_get_fraction (structure, "framerate",
1920             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1921       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1922         gint rate = 0;
1923         stream->subtype = FOURCC_soun;
1924         gst_structure_get_int (structure, "channels",
1925             &CUR_STREAM (stream)->n_channels);
1926         gst_structure_get_int (structure, "rate", &rate);
1927         CUR_STREAM (stream)->rate = rate;
1928       }
1929     }
1930     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1931   } else {
1932     demux->mss_mode = FALSE;
1933   }
1934
1935   return TRUE;
1936 }
1937
1938 static void
1939 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1940 {
1941   gint i;
1942
1943   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1944   gst_pad_stop_task (qtdemux->sinkpad);
1945
1946   if (hard || qtdemux->upstream_format_is_time) {
1947     qtdemux->state = QTDEMUX_STATE_INITIAL;
1948     qtdemux->neededbytes = 16;
1949     qtdemux->todrop = 0;
1950     qtdemux->pullbased = FALSE;
1951     g_clear_pointer (&qtdemux->redirect_location, g_free);
1952     qtdemux->first_mdat = -1;
1953     qtdemux->header_size = 0;
1954     qtdemux->mdatoffset = -1;
1955     qtdemux->restoredata_offset = -1;
1956     if (qtdemux->mdatbuffer)
1957       gst_buffer_unref (qtdemux->mdatbuffer);
1958     if (qtdemux->restoredata_buffer)
1959       gst_buffer_unref (qtdemux->restoredata_buffer);
1960     qtdemux->mdatbuffer = NULL;
1961     qtdemux->restoredata_buffer = NULL;
1962     qtdemux->mdatleft = 0;
1963     qtdemux->mdatsize = 0;
1964     if (qtdemux->comp_brands)
1965       gst_buffer_unref (qtdemux->comp_brands);
1966     qtdemux->comp_brands = NULL;
1967     qtdemux->last_moov_offset = -1;
1968     if (qtdemux->moov_node_compressed) {
1969       g_node_destroy (qtdemux->moov_node_compressed);
1970       if (qtdemux->moov_node)
1971         g_free (qtdemux->moov_node->data);
1972     }
1973     qtdemux->moov_node_compressed = NULL;
1974     if (qtdemux->moov_node)
1975       g_node_destroy (qtdemux->moov_node);
1976     qtdemux->moov_node = NULL;
1977     if (qtdemux->tag_list)
1978       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
1979     qtdemux->tag_list = gst_tag_list_new_empty ();
1980     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
1981 #if 0
1982     if (qtdemux->element_index)
1983       gst_object_unref (qtdemux->element_index);
1984     qtdemux->element_index = NULL;
1985 #endif
1986     qtdemux->major_brand = 0;
1987     qtdemux->upstream_format_is_time = FALSE;
1988     qtdemux->upstream_seekable = FALSE;
1989     qtdemux->upstream_size = 0;
1990
1991     qtdemux->fragment_start = -1;
1992     qtdemux->fragment_start_offset = -1;
1993     qtdemux->duration = 0;
1994     qtdemux->moof_offset = 0;
1995     qtdemux->chapters_track_id = 0;
1996     qtdemux->have_group_id = FALSE;
1997     qtdemux->group_id = G_MAXUINT;
1998
1999     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2000         NULL);
2001     g_queue_clear (&qtdemux->protection_event_queue);
2002
2003     qtdemux->received_seek = FALSE;
2004     qtdemux->first_moof_already_parsed = FALSE;
2005   }
2006   qtdemux->offset = 0;
2007   gst_adapter_clear (qtdemux->adapter);
2008   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2009   qtdemux->need_segment = TRUE;
2010
2011   if (hard) {
2012     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2013     qtdemux->trickmode_interval = 0;
2014     g_ptr_array_set_size (qtdemux->active_streams, 0);
2015     g_ptr_array_set_size (qtdemux->old_streams, 0);
2016     qtdemux->n_video_streams = 0;
2017     qtdemux->n_audio_streams = 0;
2018     qtdemux->n_sub_streams = 0;
2019     qtdemux->exposed = FALSE;
2020     qtdemux->fragmented = FALSE;
2021     qtdemux->mss_mode = FALSE;
2022     gst_caps_replace (&qtdemux->media_caps, NULL);
2023     qtdemux->timescale = 0;
2024     qtdemux->got_moov = FALSE;
2025     qtdemux->cenc_aux_info_offset = 0;
2026     qtdemux->cenc_aux_info_sizes = NULL;
2027     qtdemux->cenc_aux_sample_count = 0;
2028     if (qtdemux->protection_system_ids) {
2029       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2030       qtdemux->protection_system_ids = NULL;
2031     }
2032     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2033         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2034         GST_BIN_FLAG_STREAMS_AWARE);
2035
2036     if (qtdemux->preferred_protection_system_id) {
2037       g_free (qtdemux->preferred_protection_system_id);
2038       qtdemux->preferred_protection_system_id = NULL;
2039     }
2040   } else if (qtdemux->mss_mode) {
2041     gst_flow_combiner_reset (qtdemux->flowcombiner);
2042     g_ptr_array_foreach (qtdemux->active_streams,
2043         (GFunc) gst_qtdemux_stream_clear, NULL);
2044   } else {
2045     gst_flow_combiner_reset (qtdemux->flowcombiner);
2046     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2047       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2048       stream->sent_eos = FALSE;
2049       stream->time_position = 0;
2050       stream->accumulated_base = 0;
2051       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2052     }
2053   }
2054 }
2055
2056
2057 /* Maps the @segment to the qt edts internal segments and pushes
2058  * the corresponding segment event.
2059  *
2060  * If it ends up being at a empty segment, a gap will be pushed and the next
2061  * edts segment will be activated in sequence.
2062  *
2063  * To be used in push-mode only */
2064 static void
2065 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2066 {
2067   gint i, iter;
2068
2069   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2070     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2071
2072     stream->time_position = segment->start;
2073
2074     /* in push mode we should be guaranteed that we will have empty segments
2075      * at the beginning and then one segment after, other scenarios are not
2076      * supported and are discarded when parsing the edts */
2077     for (i = 0; i < stream->n_segments; i++) {
2078       if (stream->segments[i].stop_time > segment->start) {
2079         /* push the empty segment and move to the next one */
2080         gst_qtdemux_activate_segment (qtdemux, stream, i,
2081             stream->time_position);
2082         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2083           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2084               stream->time_position);
2085
2086           /* accumulate previous segments */
2087           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2088             stream->accumulated_base +=
2089                 (stream->segment.stop -
2090                 stream->segment.start) / ABS (stream->segment.rate);
2091           continue;
2092         }
2093
2094         g_assert (i == stream->n_segments - 1);
2095       }
2096     }
2097   }
2098 }
2099
2100 static void
2101 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2102     GPtrArray * src)
2103 {
2104   guint i;
2105   guint len;
2106
2107   len = src->len;
2108
2109   if (len == 0)
2110     return;
2111
2112   for (i = 0; i < len; i++) {
2113     QtDemuxStream *stream = g_ptr_array_index (src, i);
2114
2115 #ifndef GST_DISABLE_GST_DEBUG
2116     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2117         stream, GST_STR_NULL (stream->stream_id), dest);
2118 #endif
2119     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2120   }
2121
2122   g_ptr_array_set_size (src, 0);
2123 }
2124
2125 static gboolean
2126 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2127     GstEvent * event)
2128 {
2129   GstQTDemux *demux = GST_QTDEMUX (parent);
2130   gboolean res = TRUE;
2131
2132   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2133
2134   switch (GST_EVENT_TYPE (event)) {
2135     case GST_EVENT_SEGMENT:
2136     {
2137       gint64 offset = 0;
2138       QtDemuxStream *stream;
2139       gint idx;
2140       GstSegment segment;
2141
2142       /* some debug output */
2143       gst_event_copy_segment (event, &segment);
2144       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2145           &segment);
2146
2147       if (segment.format == GST_FORMAT_TIME) {
2148         demux->upstream_format_is_time = TRUE;
2149         demux->segment_seqnum = gst_event_get_seqnum (event);
2150       } else {
2151         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2152             "not in time format");
2153
2154         /* chain will send initial newsegment after pads have been added */
2155         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2156           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2157           goto exit;
2158         }
2159       }
2160
2161       /* check if this matches a time seek we received previously
2162        * FIXME for backwards compatibility reasons we use the
2163        * seek_offset here to compare. In the future we might want to
2164        * change this to use the seqnum as it uniquely should identify
2165        * the segment that corresponds to the seek. */
2166       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2167           ", received segment offset %" G_GINT64_FORMAT,
2168           demux->seek_offset, segment.start);
2169       if (segment.format == GST_FORMAT_BYTES
2170           && demux->seek_offset == segment.start) {
2171         GST_OBJECT_LOCK (demux);
2172         offset = segment.start;
2173
2174         segment.format = GST_FORMAT_TIME;
2175         segment.start = demux->push_seek_start;
2176         segment.stop = demux->push_seek_stop;
2177         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2178             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2179             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2180         GST_OBJECT_UNLOCK (demux);
2181       }
2182
2183       /* we only expect a BYTE segment, e.g. following a seek */
2184       if (segment.format == GST_FORMAT_BYTES) {
2185         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2186           offset = segment.start;
2187
2188           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2189               NULL, (gint64 *) & segment.start);
2190           if ((gint64) segment.start < 0)
2191             segment.start = 0;
2192         }
2193         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2194           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2195               NULL, (gint64 *) & segment.stop);
2196           /* keyframe seeking should already arrange for start >= stop,
2197            * but make sure in other rare cases */
2198           segment.stop = MAX (segment.stop, segment.start);
2199         }
2200       } else if (segment.format == GST_FORMAT_TIME) {
2201         /* push all data on the adapter before starting this
2202          * new segment */
2203         gst_qtdemux_process_adapter (demux, TRUE);
2204       } else {
2205         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2206         goto exit;
2207       }
2208
2209       /* We shouldn't modify upstream driven TIME FORMAT segment */
2210       if (!demux->upstream_format_is_time) {
2211         /* accept upstream's notion of segment and distribute along */
2212         segment.format = GST_FORMAT_TIME;
2213         segment.position = segment.time = segment.start;
2214         segment.duration = demux->segment.duration;
2215         segment.base = gst_segment_to_running_time (&demux->segment,
2216             GST_FORMAT_TIME, demux->segment.position);
2217       }
2218
2219       gst_segment_copy_into (&segment, &demux->segment);
2220       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2221
2222       /* map segment to internal qt segments and push on each stream */
2223       if (QTDEMUX_N_STREAMS (demux)) {
2224         demux->need_segment = TRUE;
2225         gst_qtdemux_check_send_pending_segment (demux);
2226       }
2227
2228       /* clear leftover in current segment, if any */
2229       gst_adapter_clear (demux->adapter);
2230
2231       /* set up streaming thread */
2232       demux->offset = offset;
2233       if (demux->upstream_format_is_time) {
2234         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2235             "set values to restart reading from a new atom");
2236         demux->neededbytes = 16;
2237         demux->todrop = 0;
2238       } else {
2239         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2240             NULL);
2241         if (stream) {
2242           demux->todrop = stream->samples[idx].offset - offset;
2243           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2244         } else {
2245           /* set up for EOS */
2246           demux->neededbytes = -1;
2247           demux->todrop = 0;
2248         }
2249       }
2250     exit:
2251       gst_event_unref (event);
2252       res = TRUE;
2253       goto drop;
2254     }
2255     case GST_EVENT_FLUSH_START:
2256     {
2257       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2258         gst_event_unref (event);
2259         goto drop;
2260       }
2261       QTDEMUX_EXPOSE_LOCK (demux);
2262       res = gst_pad_event_default (demux->sinkpad, parent, event);
2263       QTDEMUX_EXPOSE_UNLOCK (demux);
2264       goto drop;
2265     }
2266     case GST_EVENT_FLUSH_STOP:
2267     {
2268       guint64 dur;
2269
2270       dur = demux->segment.duration;
2271       gst_qtdemux_reset (demux, FALSE);
2272       demux->segment.duration = dur;
2273
2274       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2275         gst_event_unref (event);
2276         goto drop;
2277       }
2278       break;
2279     }
2280     case GST_EVENT_EOS:
2281       /* If we are in push mode, and get an EOS before we've seen any streams,
2282        * then error out - we have nowhere to send the EOS */
2283       if (!demux->pullbased) {
2284         gint i;
2285         gboolean has_valid_stream = FALSE;
2286         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2287           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2288             has_valid_stream = TRUE;
2289             break;
2290           }
2291         }
2292         if (!has_valid_stream)
2293           gst_qtdemux_post_no_playable_stream_error (demux);
2294         else {
2295           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2296               (guint) gst_adapter_available (demux->adapter));
2297           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2298             res = FALSE;
2299           }
2300         }
2301       }
2302       break;
2303     case GST_EVENT_CAPS:{
2304       GstCaps *caps = NULL;
2305
2306       gst_event_parse_caps (event, &caps);
2307       gst_qtdemux_setcaps (demux, caps);
2308       res = TRUE;
2309       gst_event_unref (event);
2310       goto drop;
2311     }
2312     case GST_EVENT_PROTECTION:
2313     {
2314       const gchar *system_id = NULL;
2315
2316       gst_event_parse_protection (event, &system_id, NULL, NULL);
2317       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2318           system_id);
2319       gst_qtdemux_append_protection_system_id (demux, system_id);
2320       /* save the event for later, for source pads that have not been created */
2321       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2322       /* send it to all pads that already exist */
2323       gst_qtdemux_push_event (demux, event);
2324       res = TRUE;
2325       goto drop;
2326     }
2327     case GST_EVENT_STREAM_START:
2328     {
2329       res = TRUE;
2330       gst_event_unref (event);
2331
2332       /* Drain all the buffers */
2333       gst_qtdemux_process_adapter (demux, TRUE);
2334       gst_qtdemux_reset (demux, FALSE);
2335       /* We expect new moov box after new stream-start event */
2336       if (demux->exposed) {
2337         gst_qtdemux_stream_concat (demux,
2338             demux->old_streams, demux->active_streams);
2339       }
2340
2341       goto drop;
2342     }
2343     default:
2344       break;
2345   }
2346
2347   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2348
2349 drop:
2350   return res;
2351 }
2352
2353 static gboolean
2354 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2355     GstQuery * query)
2356 {
2357   GstQTDemux *demux = GST_QTDEMUX (parent);
2358   gboolean res = FALSE;
2359
2360   switch (GST_QUERY_TYPE (query)) {
2361     case GST_QUERY_BITRATE:
2362     {
2363       GstClockTime duration;
2364
2365       /* populate demux->upstream_size if not done yet */
2366       gst_qtdemux_check_seekability (demux);
2367
2368       if (demux->upstream_size != -1
2369           && gst_qtdemux_get_duration (demux, &duration)) {
2370         guint bitrate =
2371             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2372             duration);
2373
2374         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2375             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2376             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2377
2378         /* TODO: better results based on ranges/index tables */
2379         gst_query_set_bitrate (query, bitrate);
2380         res = TRUE;
2381       }
2382       break;
2383     }
2384     default:
2385       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2386       break;
2387   }
2388
2389   return res;
2390 }
2391
2392
2393 #if 0
2394 static void
2395 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2396 {
2397   GstQTDemux *demux = GST_QTDEMUX (element);
2398
2399   GST_OBJECT_LOCK (demux);
2400   if (demux->element_index)
2401     gst_object_unref (demux->element_index);
2402   if (index) {
2403     demux->element_index = gst_object_ref (index);
2404   } else {
2405     demux->element_index = NULL;
2406   }
2407   GST_OBJECT_UNLOCK (demux);
2408   /* object lock might be taken again */
2409   if (index)
2410     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2411   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2412       demux->element_index, demux->index_id);
2413 }
2414
2415 static GstIndex *
2416 gst_qtdemux_get_index (GstElement * element)
2417 {
2418   GstIndex *result = NULL;
2419   GstQTDemux *demux = GST_QTDEMUX (element);
2420
2421   GST_OBJECT_LOCK (demux);
2422   if (demux->element_index)
2423     result = gst_object_ref (demux->element_index);
2424   GST_OBJECT_UNLOCK (demux);
2425
2426   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2427
2428   return result;
2429 }
2430 #endif
2431
2432 static void
2433 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2434 {
2435   g_free ((gpointer) stream->stco.data);
2436   stream->stco.data = NULL;
2437   g_free ((gpointer) stream->stsz.data);
2438   stream->stsz.data = NULL;
2439   g_free ((gpointer) stream->stsc.data);
2440   stream->stsc.data = NULL;
2441   g_free ((gpointer) stream->stts.data);
2442   stream->stts.data = NULL;
2443   g_free ((gpointer) stream->stss.data);
2444   stream->stss.data = NULL;
2445   g_free ((gpointer) stream->stps.data);
2446   stream->stps.data = NULL;
2447   g_free ((gpointer) stream->ctts.data);
2448   stream->ctts.data = NULL;
2449 }
2450
2451 static void
2452 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2453 {
2454   g_free (stream->segments);
2455   stream->segments = NULL;
2456   stream->segment_index = -1;
2457   stream->accumulated_base = 0;
2458 }
2459
2460 static void
2461 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2462 {
2463   g_free (stream->samples);
2464   stream->samples = NULL;
2465   gst_qtdemux_stbl_free (stream);
2466
2467   /* fragments */
2468   g_free (stream->ra_entries);
2469   stream->ra_entries = NULL;
2470   stream->n_ra_entries = 0;
2471
2472   stream->sample_index = -1;
2473   stream->stbl_index = -1;
2474   stream->n_samples = 0;
2475   stream->time_position = 0;
2476
2477   stream->n_samples_moof = 0;
2478   stream->duration_moof = 0;
2479   stream->duration_last_moof = 0;
2480 }
2481
2482 static void
2483 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2484 {
2485   gint i;
2486   if (stream->allocator)
2487     gst_object_unref (stream->allocator);
2488   while (stream->buffers) {
2489     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2490     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2491   }
2492   for (i = 0; i < stream->stsd_entries_length; i++) {
2493     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2494     if (entry->rgb8_palette) {
2495       gst_memory_unref (entry->rgb8_palette);
2496       entry->rgb8_palette = NULL;
2497     }
2498     entry->sparse = FALSE;
2499   }
2500
2501   if (stream->stream_tags)
2502     gst_tag_list_unref (stream->stream_tags);
2503
2504   stream->stream_tags = gst_tag_list_new_empty ();
2505   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2506   g_free (stream->redirect_uri);
2507   stream->redirect_uri = NULL;
2508   stream->sent_eos = FALSE;
2509   stream->protected = FALSE;
2510   if (stream->protection_scheme_info) {
2511     if (stream->protection_scheme_type == FOURCC_cenc) {
2512       QtDemuxCencSampleSetInfo *info =
2513           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2514       if (info->default_properties)
2515         gst_structure_free (info->default_properties);
2516       if (info->crypto_info)
2517         g_ptr_array_free (info->crypto_info, TRUE);
2518     }
2519     g_free (stream->protection_scheme_info);
2520     stream->protection_scheme_info = NULL;
2521   }
2522   stream->protection_scheme_type = 0;
2523   stream->protection_scheme_version = 0;
2524   g_queue_foreach (&stream->protection_scheme_event_queue,
2525       (GFunc) gst_event_unref, NULL);
2526   g_queue_clear (&stream->protection_scheme_event_queue);
2527   gst_qtdemux_stream_flush_segments_data (stream);
2528   gst_qtdemux_stream_flush_samples_data (stream);
2529 }
2530
2531 static void
2532 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2533 {
2534   gint i;
2535   gst_qtdemux_stream_clear (stream);
2536   for (i = 0; i < stream->stsd_entries_length; i++) {
2537     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2538     if (entry->caps) {
2539       gst_caps_unref (entry->caps);
2540       entry->caps = NULL;
2541     }
2542   }
2543   g_free (stream->stsd_entries);
2544   stream->stsd_entries = NULL;
2545   stream->stsd_entries_length = 0;
2546 }
2547
2548 static QtDemuxStream *
2549 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2550 {
2551   g_atomic_int_add (&stream->ref_count, 1);
2552
2553   return stream;
2554 }
2555
2556 static void
2557 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2558 {
2559   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2560     gst_qtdemux_stream_reset (stream);
2561     gst_tag_list_unref (stream->stream_tags);
2562     if (stream->pad) {
2563       GstQTDemux *demux = stream->demux;
2564       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2565       GST_OBJECT_LOCK (demux);
2566       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2567       GST_OBJECT_UNLOCK (demux);
2568     }
2569     g_free (stream->stream_id);
2570     g_free (stream);
2571   }
2572 }
2573
2574 static GstStateChangeReturn
2575 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2576 {
2577   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2578   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2579
2580   switch (transition) {
2581     case GST_STATE_CHANGE_READY_TO_PAUSED:
2582       gst_qtdemux_reset (qtdemux, TRUE);
2583       break;
2584     default:
2585       break;
2586   }
2587
2588   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2589
2590   switch (transition) {
2591     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2592       gst_qtdemux_reset (qtdemux, TRUE);
2593       break;
2594     }
2595     default:
2596       break;
2597   }
2598
2599   return result;
2600 }
2601
2602 static void
2603 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2604 {
2605   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2606
2607   g_return_if_fail (GST_IS_CONTEXT (context));
2608
2609   if (gst_context_has_context_type (context,
2610           "drm-preferred-decryption-system-id")) {
2611     const GstStructure *s;
2612
2613     s = gst_context_get_structure (context);
2614     g_free (qtdemux->preferred_protection_system_id);
2615     qtdemux->preferred_protection_system_id =
2616         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2617     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2618         qtdemux->preferred_protection_system_id);
2619   }
2620
2621   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2622 }
2623
2624 static void
2625 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2626 {
2627   /* counts as header data */
2628   qtdemux->header_size += length;
2629
2630   /* only consider at least a sufficiently complete ftyp atom */
2631   if (length >= 20) {
2632     GstBuffer *buf;
2633
2634     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2635     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2636         GST_FOURCC_ARGS (qtdemux->major_brand));
2637     if (qtdemux->comp_brands)
2638       gst_buffer_unref (qtdemux->comp_brands);
2639     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2640     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2641   }
2642 }
2643
2644 static void
2645 qtdemux_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2646     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2647     const guint8 * kid)
2648 {
2649   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2650   gst_buffer_fill (kid_buf, 0, kid, 16);
2651   if (info->default_properties)
2652     gst_structure_free (info->default_properties);
2653   info->default_properties =
2654       gst_structure_new ("application/x-cenc",
2655       "iv_size", G_TYPE_UINT, iv_size,
2656       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2657       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2658   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2659       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2660   gst_buffer_unref (kid_buf);
2661 }
2662
2663 static gboolean
2664 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2665     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2666 {
2667   guint32 algorithm_id = 0;
2668   const guint8 *kid;
2669   gboolean is_encrypted = TRUE;
2670   guint8 iv_size = 8;
2671
2672   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2673     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2674     return FALSE;
2675   }
2676
2677   algorithm_id >>= 8;
2678   if (algorithm_id == 0) {
2679     is_encrypted = FALSE;
2680   } else if (algorithm_id == 1) {
2681     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2682   } else if (algorithm_id == 2) {
2683     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2684   }
2685
2686   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2687     return FALSE;
2688
2689   if (!gst_byte_reader_get_data (br, 16, &kid))
2690     return FALSE;
2691
2692   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2693       is_encrypted, iv_size, kid);
2694   gst_structure_set (info->default_properties, "piff_algorithm_id",
2695       G_TYPE_UINT, algorithm_id, NULL);
2696   return TRUE;
2697 }
2698
2699
2700 static void
2701 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2702     guint offset)
2703 {
2704   GstByteReader br;
2705   guint8 version;
2706   guint32 flags = 0;
2707   guint i;
2708   guint iv_size = 8;
2709   QtDemuxStream *stream;
2710   GstStructure *structure;
2711   QtDemuxCencSampleSetInfo *ss_info = NULL;
2712   const gchar *system_id;
2713   gboolean uses_sub_sample_encryption = FALSE;
2714   guint32 sample_count;
2715
2716   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2717     return;
2718
2719   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2720
2721   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2722   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2723     GST_WARNING_OBJECT (qtdemux,
2724         "Attempting PIFF box parsing on an unencrypted stream.");
2725     return;
2726   }
2727
2728   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2729       G_TYPE_STRING, &system_id, NULL);
2730   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2731
2732   stream->protected = TRUE;
2733   stream->protection_scheme_type = FOURCC_cenc;
2734
2735   if (!stream->protection_scheme_info)
2736     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2737
2738   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2739   if (!ss_info->default_properties) {
2740     ss_info->default_properties =
2741         gst_structure_new ("application/x-cenc",
2742         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2743         NULL);
2744
2745   }
2746
2747   if (ss_info->crypto_info) {
2748     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2749     g_ptr_array_free (ss_info->crypto_info, TRUE);
2750     ss_info->crypto_info = NULL;
2751   }
2752
2753   /* skip UUID */
2754   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2755
2756   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2757     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2758     return;
2759   }
2760
2761   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2762     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2763     return;
2764   }
2765
2766   if ((flags & 0x000001)) {
2767     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2768             &br))
2769       return;
2770   } else if ((flags & 0x000002)) {
2771     uses_sub_sample_encryption = TRUE;
2772   }
2773
2774   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2775           &iv_size)) {
2776     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2777     return;
2778   }
2779
2780   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2781     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2782     return;
2783   }
2784
2785   ss_info->crypto_info =
2786       g_ptr_array_new_full (sample_count,
2787       (GDestroyNotify) qtdemux_gst_structure_free);
2788
2789   for (i = 0; i < sample_count; ++i) {
2790     GstStructure *properties;
2791     guint8 *data;
2792     GstBuffer *buf;
2793
2794     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2795     if (properties == NULL) {
2796       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2797       qtdemux->cenc_aux_sample_count = i;
2798       return;
2799     }
2800
2801     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2802       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2803       gst_structure_free (properties);
2804       qtdemux->cenc_aux_sample_count = i;
2805       return;
2806     }
2807     buf = gst_buffer_new_wrapped (data, iv_size);
2808     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2809     gst_buffer_unref (buf);
2810
2811     if (uses_sub_sample_encryption) {
2812       guint16 n_subsamples;
2813       const GValue *kid_buf_value;
2814
2815       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2816           || n_subsamples == 0) {
2817         GST_ERROR_OBJECT (qtdemux,
2818             "failed to get subsample count for sample %u", i);
2819         gst_structure_free (properties);
2820         qtdemux->cenc_aux_sample_count = i;
2821         return;
2822       }
2823       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2824       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2825         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2826             i);
2827         gst_structure_free (properties);
2828         qtdemux->cenc_aux_sample_count = i;
2829         return;
2830       }
2831       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2832
2833       kid_buf_value =
2834           gst_structure_get_value (ss_info->default_properties, "kid");
2835
2836       gst_structure_set (properties,
2837           "subsample_count", G_TYPE_UINT, n_subsamples,
2838           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2839       gst_structure_set_value (properties, "kid", kid_buf_value);
2840       gst_buffer_unref (buf);
2841     } else {
2842       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2843     }
2844
2845     g_ptr_array_add (ss_info->crypto_info, properties);
2846   }
2847
2848   qtdemux->cenc_aux_sample_count = sample_count;
2849 }
2850
2851 static void
2852 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2853 {
2854   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2855     0x97, 0xA9, 0x42, 0xE8,
2856     0x9C, 0x71, 0x99, 0x94,
2857     0x91, 0xE3, 0xAF, 0xAC
2858   };
2859   static const guint8 playready_uuid[] = {
2860     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2861     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2862   };
2863
2864   static const guint8 piff_sample_encryption_uuid[] = {
2865     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2866     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2867   };
2868
2869   guint offset;
2870
2871   /* counts as header data */
2872   qtdemux->header_size += length;
2873
2874   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2875
2876   if (length <= offset + 16) {
2877     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2878     return;
2879   }
2880
2881   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2882     GstBuffer *buf;
2883     GstTagList *taglist;
2884
2885     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2886         length - offset - 16, NULL);
2887     taglist = gst_tag_list_from_xmp_buffer (buf);
2888     gst_buffer_unref (buf);
2889
2890     /* make sure we have a usable taglist */
2891     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2892
2893     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2894
2895   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2896     int len;
2897     const gunichar2 *s_utf16;
2898     char *contents;
2899
2900     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2901     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2902     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2903     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2904
2905     g_free (contents);
2906
2907     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2908         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2909         (NULL));
2910   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2911     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2912   } else {
2913     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2914         GST_READ_UINT32_LE (buffer + offset),
2915         GST_READ_UINT32_LE (buffer + offset + 4),
2916         GST_READ_UINT32_LE (buffer + offset + 8),
2917         GST_READ_UINT32_LE (buffer + offset + 12));
2918   }
2919 }
2920
2921 static void
2922 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2923 {
2924   GstSidxParser sidx_parser;
2925   GstIsoffParserResult res;
2926   guint consumed;
2927
2928   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2929
2930   res =
2931       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2932       &consumed);
2933   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2934   if (res == GST_ISOFF_QT_PARSER_DONE) {
2935     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2936   }
2937   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2938 }
2939
2940 /* caller verifies at least 8 bytes in buf */
2941 static void
2942 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2943     guint64 * plength, guint32 * pfourcc)
2944 {
2945   guint64 length;
2946   guint32 fourcc;
2947
2948   length = QT_UINT32 (data);
2949   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2950   fourcc = QT_FOURCC (data + 4);
2951   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2952
2953   if (length == 0) {
2954     length = G_MAXUINT64;
2955   } else if (length == 1 && size >= 16) {
2956     /* this means we have an extended size, which is the 64 bit value of
2957      * the next 8 bytes */
2958     length = QT_UINT64 (data + 8);
2959     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2960   }
2961
2962   if (plength)
2963     *plength = length;
2964   if (pfourcc)
2965     *pfourcc = fourcc;
2966 }
2967
2968 static gboolean
2969 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2970 {
2971   guint32 version = 0;
2972   GstClockTime duration = 0;
2973
2974   if (!gst_byte_reader_get_uint32_be (br, &version))
2975     goto failed;
2976
2977   version >>= 24;
2978   if (version == 1) {
2979     if (!gst_byte_reader_get_uint64_be (br, &duration))
2980       goto failed;
2981   } else {
2982     guint32 dur = 0;
2983
2984     if (!gst_byte_reader_get_uint32_be (br, &dur))
2985       goto failed;
2986     duration = dur;
2987   }
2988
2989   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2990   qtdemux->duration = duration;
2991
2992   return TRUE;
2993
2994 failed:
2995   {
2996     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2997     return FALSE;
2998   }
2999 }
3000
3001 static gboolean
3002 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3003     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3004 {
3005   if (!stream->parsed_trex && qtdemux->moov_node) {
3006     GNode *mvex, *trex;
3007     GstByteReader trex_data;
3008
3009     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3010     if (mvex) {
3011       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3012           &trex_data);
3013       while (trex) {
3014         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3015
3016         /* skip version/flags */
3017         if (!gst_byte_reader_skip (&trex_data, 4))
3018           goto next;
3019         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3020           goto next;
3021         if (id != stream->track_id)
3022           goto next;
3023         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3024           goto next;
3025         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3026           goto next;
3027         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3028           goto next;
3029         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3030           goto next;
3031
3032         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3033             "duration %d,  size %d, flags 0x%x", stream->track_id,
3034             dur, size, flags);
3035
3036         stream->parsed_trex = TRUE;
3037         stream->def_sample_description_index = sdi;
3038         stream->def_sample_duration = dur;
3039         stream->def_sample_size = size;
3040         stream->def_sample_flags = flags;
3041
3042       next:
3043         /* iterate all siblings */
3044         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3045             &trex_data);
3046       }
3047     }
3048   }
3049
3050   *ds_duration = stream->def_sample_duration;
3051   *ds_size = stream->def_sample_size;
3052   *ds_flags = stream->def_sample_flags;
3053
3054   /* even then, above values are better than random ... */
3055   if (G_UNLIKELY (!stream->parsed_trex)) {
3056     GST_WARNING_OBJECT (qtdemux,
3057         "failed to find fragment defaults for stream %d", stream->track_id);
3058     return FALSE;
3059   }
3060
3061   return TRUE;
3062 }
3063
3064 /* This method should be called whenever a more accurate duration might
3065  * have been found. It will update all relevant variables if/where needed
3066  */
3067 static void
3068 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3069 {
3070   guint i;
3071   guint64 movdur;
3072   GstClockTime prevdur;
3073
3074   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3075
3076   if (movdur > qtdemux->duration) {
3077     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3078     GST_DEBUG_OBJECT (qtdemux,
3079         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3080         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3081     qtdemux->duration = movdur;
3082     GST_DEBUG_OBJECT (qtdemux,
3083         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3084         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3085         GST_TIME_ARGS (qtdemux->segment.stop));
3086     if (qtdemux->segment.duration == prevdur) {
3087       /* If the current segment has duration/stop identical to previous duration
3088        * update them also (because they were set at that point in time with
3089        * the wrong duration */
3090       /* We convert the value *from* the timescale version to avoid rounding errors */
3091       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3092       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3093       qtdemux->segment.duration = fixeddur;
3094       qtdemux->segment.stop = fixeddur;
3095     }
3096   }
3097
3098   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3099     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3100
3101     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3102     if (movdur > stream->duration) {
3103       GST_DEBUG_OBJECT (qtdemux,
3104           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3105           GST_TIME_ARGS (duration));
3106       stream->duration = movdur;
3107       /* internal duration tracking state has been updated above, so */
3108       /* preserve an open-ended dummy segment rather than repeatedly updating
3109        * it and spamming downstream accordingly with segment events */
3110       if (stream->dummy_segment &&
3111           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3112         /* Update all dummy values to new duration */
3113         stream->segments[0].stop_time = duration;
3114         stream->segments[0].duration = duration;
3115         stream->segments[0].media_stop = duration;
3116
3117         /* let downstream know we possibly have a new stop time */
3118         if (stream->segment_index != -1) {
3119           GstClockTime pos;
3120
3121           if (qtdemux->segment.rate >= 0) {
3122             pos = stream->segment.start;
3123           } else {
3124             pos = stream->segment.stop;
3125           }
3126
3127           gst_qtdemux_stream_update_segment (qtdemux, stream,
3128               stream->segment_index, pos, NULL, NULL);
3129         }
3130       }
3131     }
3132   }
3133 }
3134
3135 static gboolean
3136 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3137     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3138     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3139     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3140     gboolean has_tfdt)
3141 {
3142   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3143   guint64 timestamp;
3144   gint32 data_offset = 0;
3145   guint32 flags = 0, first_flags = 0, samples_count = 0;
3146   gint i;
3147   guint8 *data;
3148   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3149   QtDemuxSample *sample;
3150   gboolean ismv = FALSE;
3151   gint64 initial_offset;
3152
3153   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3154       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3155       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3156       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3157
3158   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3159     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3160     return TRUE;
3161   }
3162
3163   /* presence of stss or not can't really tell us much,
3164    * and flags and so on tend to be marginally reliable in these files */
3165   if (stream->subtype == FOURCC_soun) {
3166     GST_DEBUG_OBJECT (qtdemux,
3167         "sound track in fragmented file; marking all keyframes");
3168     stream->all_keyframe = TRUE;
3169   }
3170
3171   if (!gst_byte_reader_skip (trun, 1) ||
3172       !gst_byte_reader_get_uint24_be (trun, &flags))
3173     goto fail;
3174
3175   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3176     goto fail;
3177
3178   if (flags & TR_DATA_OFFSET) {
3179     /* note this is really signed */
3180     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3181       goto fail;
3182     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3183     /* default base offset = first byte of moof */
3184     if (*base_offset == -1) {
3185       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3186       *base_offset = moof_offset;
3187     }
3188     *running_offset = *base_offset + data_offset;
3189   } else {
3190     /* if no offset at all, that would mean data starts at moof start,
3191      * which is a bit wrong and is ismv crappy way, so compensate
3192      * assuming data is in mdat following moof */
3193     if (*base_offset == -1) {
3194       *base_offset = moof_offset + moof_length + 8;
3195       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3196       ismv = TRUE;
3197     }
3198     if (*running_offset == -1)
3199       *running_offset = *base_offset;
3200   }
3201
3202   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3203       *running_offset);
3204   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3205       data_offset, flags, samples_count);
3206
3207   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3208     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3209       GST_DEBUG_OBJECT (qtdemux,
3210           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3211       flags ^= TR_FIRST_SAMPLE_FLAGS;
3212     } else {
3213       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3214         goto fail;
3215       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3216     }
3217   }
3218
3219   /* FIXME ? spec says other bits should also be checked to determine
3220    * entry size (and prefix size for that matter) */
3221   entry_size = 0;
3222   dur_offset = size_offset = 0;
3223   if (flags & TR_SAMPLE_DURATION) {
3224     GST_LOG_OBJECT (qtdemux, "entry duration present");
3225     dur_offset = entry_size;
3226     entry_size += 4;
3227   }
3228   if (flags & TR_SAMPLE_SIZE) {
3229     GST_LOG_OBJECT (qtdemux, "entry size present");
3230     size_offset = entry_size;
3231     entry_size += 4;
3232   }
3233   if (flags & TR_SAMPLE_FLAGS) {
3234     GST_LOG_OBJECT (qtdemux, "entry flags present");
3235     flags_offset = entry_size;
3236     entry_size += 4;
3237   }
3238   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3239     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3240     ct_offset = entry_size;
3241     entry_size += 4;
3242   }
3243
3244   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3245     goto fail;
3246   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3247
3248   if (stream->n_samples + samples_count >=
3249       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3250     goto index_too_big;
3251
3252   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3253       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3254       (stream->n_samples + samples_count) *
3255       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3256
3257   /* create a new array of samples if it's the first sample parsed */
3258   if (stream->n_samples == 0) {
3259     g_assert (stream->samples == NULL);
3260     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3261     /* or try to reallocate it with space enough to insert the new samples */
3262   } else
3263     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3264         stream->n_samples + samples_count);
3265   if (stream->samples == NULL)
3266     goto out_of_memory;
3267
3268   if (qtdemux->fragment_start != -1) {
3269     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3270     qtdemux->fragment_start = -1;
3271   } else {
3272     if (stream->n_samples == 0) {
3273       if (decode_ts > 0) {
3274         timestamp = decode_ts;
3275       } else if (stream->pending_seek != NULL) {
3276         /* if we don't have a timestamp from a tfdt box, we'll use the one
3277          * from the mfra seek table */
3278         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3279             GST_TIME_ARGS (stream->pending_seek->ts));
3280
3281         /* FIXME: this is not fully correct, the timestamp refers to the random
3282          * access sample refered to in the tfra entry, which may not necessarily
3283          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3284         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3285       } else {
3286         timestamp = 0;
3287       }
3288
3289       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3290       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3291           GST_TIME_ARGS (gst_ts));
3292     } else {
3293       /* subsequent fragments extend stream */
3294       timestamp =
3295           stream->samples[stream->n_samples - 1].timestamp +
3296           stream->samples[stream->n_samples - 1].duration;
3297
3298       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3299        * difference (1 sec.) between decode_ts and timestamp, prefer the
3300        * former */
3301       if (has_tfdt && !qtdemux->upstream_format_is_time
3302           && ABSDIFF (decode_ts, timestamp) >
3303           MAX (stream->duration_last_moof / 2,
3304               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3305         GST_INFO_OBJECT (qtdemux,
3306             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3307             ") are significantly different (more than %" GST_TIME_FORMAT
3308             "), using decode_ts",
3309             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3310             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3311             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3312                     MAX (stream->duration_last_moof / 2,
3313                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3314         timestamp = decode_ts;
3315       }
3316
3317       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3318       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3319           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3320     }
3321   }
3322
3323   initial_offset = *running_offset;
3324
3325   sample = stream->samples + stream->n_samples;
3326   for (i = 0; i < samples_count; i++) {
3327     guint32 dur, size, sflags, ct;
3328
3329     /* first read sample data */
3330     if (flags & TR_SAMPLE_DURATION) {
3331       dur = QT_UINT32 (data + dur_offset);
3332     } else {
3333       dur = d_sample_duration;
3334     }
3335     if (flags & TR_SAMPLE_SIZE) {
3336       size = QT_UINT32 (data + size_offset);
3337     } else {
3338       size = d_sample_size;
3339     }
3340     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3341       if (i == 0) {
3342         sflags = first_flags;
3343       } else {
3344         sflags = d_sample_flags;
3345       }
3346     } else if (flags & TR_SAMPLE_FLAGS) {
3347       sflags = QT_UINT32 (data + flags_offset);
3348     } else {
3349       sflags = d_sample_flags;
3350     }
3351     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3352       ct = QT_UINT32 (data + ct_offset);
3353     } else {
3354       ct = 0;
3355     }
3356     data += entry_size;
3357
3358     /* fill the sample information */
3359     sample->offset = *running_offset;
3360     sample->pts_offset = ct;
3361     sample->size = size;
3362     sample->timestamp = timestamp;
3363     sample->duration = dur;
3364     /* sample-is-difference-sample */
3365     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3366      * now idea how it relates to bitfield other than massive LE/BE confusion */
3367     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3368     *running_offset += size;
3369     timestamp += dur;
3370     stream->duration_moof += dur;
3371     sample++;
3372   }
3373
3374   /* Update total duration if needed */
3375   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3376
3377   /* Pre-emptively figure out size of mdat based on trun information.
3378    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3379    * size, else we will still be able to use this when dealing with gap'ed
3380    * input */
3381   qtdemux->mdatleft = *running_offset - initial_offset;
3382   qtdemux->mdatoffset = initial_offset;
3383   qtdemux->mdatsize = qtdemux->mdatleft;
3384
3385   stream->n_samples += samples_count;
3386   stream->n_samples_moof += samples_count;
3387
3388   if (stream->pending_seek != NULL)
3389     stream->pending_seek = NULL;
3390
3391   return TRUE;
3392
3393 fail:
3394   {
3395     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3396     return FALSE;
3397   }
3398 out_of_memory:
3399   {
3400     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3401         stream->n_samples);
3402     return FALSE;
3403   }
3404 index_too_big:
3405   {
3406     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3407         "be larger than %uMB (broken file?)", stream->n_samples,
3408         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3409     return FALSE;
3410   }
3411 }
3412
3413 /* find stream with @id */
3414 static inline QtDemuxStream *
3415 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3416 {
3417   QtDemuxStream *stream;
3418   gint i;
3419
3420   /* check */
3421   if (G_UNLIKELY (!id)) {
3422     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3423     return NULL;
3424   }
3425
3426   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3427     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3428     if (stream->track_id == id)
3429       return stream;
3430   }
3431   if (qtdemux->mss_mode) {
3432     /* mss should have only 1 stream anyway */
3433     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3434   }
3435
3436   return NULL;
3437 }
3438
3439 static gboolean
3440 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3441     guint32 * fragment_number)
3442 {
3443   if (!gst_byte_reader_skip (mfhd, 4))
3444     goto fail;
3445   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3446     goto fail;
3447   return TRUE;
3448 fail:
3449   {
3450     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3451     return FALSE;
3452   }
3453 }
3454
3455 static gboolean
3456 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3457     QtDemuxStream ** stream, guint32 * default_sample_duration,
3458     guint32 * default_sample_size, guint32 * default_sample_flags,
3459     gint64 * base_offset)
3460 {
3461   guint32 flags = 0;
3462   guint32 track_id = 0;
3463
3464   if (!gst_byte_reader_skip (tfhd, 1) ||
3465       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3466     goto invalid_track;
3467
3468   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3469     goto invalid_track;
3470
3471   *stream = qtdemux_find_stream (qtdemux, track_id);
3472   if (G_UNLIKELY (!*stream))
3473     goto unknown_stream;
3474
3475   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3476     *base_offset = qtdemux->moof_offset;
3477
3478   if (flags & TF_BASE_DATA_OFFSET)
3479     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3480       goto invalid_track;
3481
3482   /* obtain stream defaults */
3483   qtdemux_parse_trex (qtdemux, *stream,
3484       default_sample_duration, default_sample_size, default_sample_flags);
3485
3486   (*stream)->stsd_sample_description_id =
3487       (*stream)->def_sample_description_index - 1;
3488
3489   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3490     guint32 sample_description_index;
3491     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3492       goto invalid_track;
3493     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3494   }
3495
3496   if (qtdemux->mss_mode) {
3497     /* mss has no stsd entry */
3498     (*stream)->stsd_sample_description_id = 0;
3499   }
3500
3501   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3502     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3503       goto invalid_track;
3504
3505   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3506     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3507       goto invalid_track;
3508
3509   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3510     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3511       goto invalid_track;
3512
3513   return TRUE;
3514
3515 invalid_track:
3516   {
3517     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3518     return FALSE;
3519   }
3520 unknown_stream:
3521   {
3522     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3523     return TRUE;
3524   }
3525 }
3526
3527 static gboolean
3528 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3529     guint64 * decode_time)
3530 {
3531   guint32 version = 0;
3532
3533   if (!gst_byte_reader_get_uint32_be (br, &version))
3534     return FALSE;
3535
3536   version >>= 24;
3537   if (version == 1) {
3538     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3539       goto failed;
3540   } else {
3541     guint32 dec_time = 0;
3542     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3543       goto failed;
3544     *decode_time = dec_time;
3545   }
3546
3547   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3548       *decode_time);
3549
3550   return TRUE;
3551
3552 failed:
3553   {
3554     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3555     return FALSE;
3556   }
3557 }
3558
3559 /* Returns a pointer to a GstStructure containing the properties of
3560  * the stream sample identified by @sample_index. The caller must unref
3561  * the returned object after use. Returns NULL if unsuccessful. */
3562 static GstStructure *
3563 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3564     QtDemuxStream * stream, guint sample_index)
3565 {
3566   QtDemuxCencSampleSetInfo *info = NULL;
3567
3568   g_return_val_if_fail (stream != NULL, NULL);
3569   g_return_val_if_fail (stream->protected, NULL);
3570   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3571
3572   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3573
3574   /* Currently, cenc properties for groups of samples are not supported, so
3575    * simply return a copy of the default sample properties */
3576   return gst_structure_copy (info->default_properties);
3577 }
3578
3579 /* Parses the sizes of sample auxiliary information contained within a stream,
3580  * as given in a saiz box. Returns array of sample_count guint8 size values,
3581  * or NULL on failure */
3582 static guint8 *
3583 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3584     GstByteReader * br, guint32 * sample_count)
3585 {
3586   guint32 flags = 0;
3587   guint8 *info_sizes;
3588   guint8 default_info_size;
3589
3590   g_return_val_if_fail (qtdemux != NULL, NULL);
3591   g_return_val_if_fail (stream != NULL, NULL);
3592   g_return_val_if_fail (br != NULL, NULL);
3593   g_return_val_if_fail (sample_count != NULL, NULL);
3594
3595   if (!gst_byte_reader_get_uint32_be (br, &flags))
3596     return NULL;
3597
3598   if (flags & 0x1) {
3599     /* aux_info_type and aux_info_type_parameter are ignored */
3600     if (!gst_byte_reader_skip (br, 8))
3601       return NULL;
3602   }
3603
3604   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3605     return NULL;
3606   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3607
3608   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3609     return NULL;
3610   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3611
3612
3613   if (default_info_size == 0) {
3614     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3615       return NULL;
3616     }
3617   } else {
3618     info_sizes = g_new (guint8, *sample_count);
3619     memset (info_sizes, default_info_size, *sample_count);
3620   }
3621
3622   return info_sizes;
3623 }
3624
3625 /* Parses the offset of sample auxiliary information contained within a stream,
3626  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3627 static gboolean
3628 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3629     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3630     guint64 * offset)
3631 {
3632   guint8 version = 0;
3633   guint32 flags = 0;
3634   guint32 aux_info_type = 0;
3635   guint32 aux_info_type_parameter = 0;
3636   guint32 entry_count;
3637   guint32 off_32;
3638   guint64 off_64;
3639   const guint8 *aux_info_type_data = NULL;
3640
3641   g_return_val_if_fail (qtdemux != NULL, FALSE);
3642   g_return_val_if_fail (stream != NULL, FALSE);
3643   g_return_val_if_fail (br != NULL, FALSE);
3644   g_return_val_if_fail (offset != NULL, FALSE);
3645
3646   if (!gst_byte_reader_get_uint8 (br, &version))
3647     return FALSE;
3648
3649   if (!gst_byte_reader_get_uint24_be (br, &flags))
3650     return FALSE;
3651
3652   if (flags & 0x1) {
3653
3654     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3655       return FALSE;
3656     aux_info_type = QT_FOURCC (aux_info_type_data);
3657
3658     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3659       return FALSE;
3660   } else if (stream->protected) {
3661     aux_info_type = stream->protection_scheme_type;
3662   } else {
3663     aux_info_type = CUR_STREAM (stream)->fourcc;
3664   }
3665
3666   if (info_type)
3667     *info_type = aux_info_type;
3668   if (info_type_parameter)
3669     *info_type_parameter = aux_info_type_parameter;
3670
3671   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3672       "aux_info_type_parameter:  %#06x",
3673       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3674
3675   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3676     return FALSE;
3677
3678   if (entry_count != 1) {
3679     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3680     return FALSE;
3681   }
3682
3683   if (version == 0) {
3684     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3685       return FALSE;
3686     *offset = (guint64) off_32;
3687   } else {
3688     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3689       return FALSE;
3690     *offset = off_64;
3691   }
3692
3693   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3694   return TRUE;
3695 }
3696
3697 static void
3698 qtdemux_gst_structure_free (GstStructure * gststructure)
3699 {
3700   if (gststructure) {
3701     gst_structure_free (gststructure);
3702   }
3703 }
3704
3705 /* Parses auxiliary information relating to samples protected using Common
3706  * Encryption (cenc); the format of this information is defined in
3707  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3708 static gboolean
3709 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3710     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3711 {
3712   QtDemuxCencSampleSetInfo *ss_info = NULL;
3713   guint8 size;
3714   gint i;
3715   GPtrArray *old_crypto_info = NULL;
3716   guint old_entries = 0;
3717
3718   g_return_val_if_fail (qtdemux != NULL, FALSE);
3719   g_return_val_if_fail (stream != NULL, FALSE);
3720   g_return_val_if_fail (br != NULL, FALSE);
3721   g_return_val_if_fail (stream->protected, FALSE);
3722   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3723
3724   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3725
3726   if (ss_info->crypto_info) {
3727     old_crypto_info = ss_info->crypto_info;
3728     /* Count number of non-null entries remaining at the tail end */
3729     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3730       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3731         break;
3732       old_entries++;
3733     }
3734   }
3735
3736   ss_info->crypto_info =
3737       g_ptr_array_new_full (sample_count + old_entries,
3738       (GDestroyNotify) qtdemux_gst_structure_free);
3739
3740   /* We preserve old entries because we parse the next moof in advance
3741    * of consuming all samples from the previous moof, and otherwise
3742    * we'd discard the corresponding crypto info for the samples
3743    * from the previous fragment. */
3744   if (old_entries) {
3745     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3746         old_entries);
3747     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3748       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3749               i));
3750       g_ptr_array_index (old_crypto_info, i) = NULL;
3751     }
3752   }
3753
3754   if (old_crypto_info) {
3755     /* Everything now belongs to the new array */
3756     g_ptr_array_free (old_crypto_info, TRUE);
3757   }
3758
3759   for (i = 0; i < sample_count; ++i) {
3760     GstStructure *properties;
3761     guint16 n_subsamples = 0;
3762     guint8 *data;
3763     guint iv_size;
3764     GstBuffer *buf;
3765
3766     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3767     if (properties == NULL) {
3768       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3769       return FALSE;
3770     }
3771     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3772       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3773       gst_structure_free (properties);
3774       return FALSE;
3775     }
3776     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3777       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3778       gst_structure_free (properties);
3779       return FALSE;
3780     }
3781     buf = gst_buffer_new_wrapped (data, iv_size);
3782     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3783     gst_buffer_unref (buf);
3784     size = info_sizes[i];
3785     if (size > iv_size) {
3786       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3787           || !(n_subsamples > 0)) {
3788         gst_structure_free (properties);
3789         GST_ERROR_OBJECT (qtdemux,
3790             "failed to get subsample count for sample %u", i);
3791         return FALSE;
3792       }
3793       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3794       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3795         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3796             i);
3797         gst_structure_free (properties);
3798         return FALSE;
3799       }
3800       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3801       if (!buf) {
3802         gst_structure_free (properties);
3803         return FALSE;
3804       }
3805       gst_structure_set (properties,
3806           "subsample_count", G_TYPE_UINT, n_subsamples,
3807           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3808       gst_buffer_unref (buf);
3809     } else {
3810       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3811     }
3812     g_ptr_array_add (ss_info->crypto_info, properties);
3813   }
3814   return TRUE;
3815 }
3816
3817 /* Converts a UUID in raw byte form to a string representation, as defined in
3818  * RFC 4122. The caller takes ownership of the returned string and is
3819  * responsible for freeing it after use. */
3820 static gchar *
3821 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3822 {
3823   const guint8 *uuid = (const guint8 *) uuid_bytes;
3824
3825   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3826       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3827       uuid[0], uuid[1], uuid[2], uuid[3],
3828       uuid[4], uuid[5], uuid[6], uuid[7],
3829       uuid[8], uuid[9], uuid[10], uuid[11],
3830       uuid[12], uuid[13], uuid[14], uuid[15]);
3831 }
3832
3833 /* Parses a Protection System Specific Header box (pssh), as defined in the
3834  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3835  * information needed by a specific content protection system in order to
3836  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3837  * otherwise. */
3838 static gboolean
3839 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3840 {
3841   gchar *sysid_string;
3842   guint32 pssh_size = QT_UINT32 (node->data);
3843   GstBuffer *pssh = NULL;
3844   GstEvent *event = NULL;
3845   guint32 parent_box_type;
3846   gint i;
3847
3848   if (G_UNLIKELY (pssh_size < 32U)) {
3849     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3850     return FALSE;
3851   }
3852
3853   sysid_string =
3854       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3855
3856   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3857
3858   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3859   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3860       gst_buffer_get_size (pssh));
3861
3862   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3863
3864   /* Push an event containing the pssh box onto the queues of all streams. */
3865   event = gst_event_new_protection (sysid_string, pssh,
3866       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3867   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3868     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3869     GST_TRACE_OBJECT (qtdemux,
3870         "adding protection event for stream %s and system %s",
3871         stream->stream_id, sysid_string);
3872     g_queue_push_tail (&stream->protection_scheme_event_queue,
3873         gst_event_ref (event));
3874   }
3875   g_free (sysid_string);
3876   gst_event_unref (event);
3877   gst_buffer_unref (pssh);
3878   return TRUE;
3879 }
3880
3881 static gboolean
3882 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3883     guint64 moof_offset, QtDemuxStream * stream)
3884 {
3885   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3886   GNode *uuid_node;
3887   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3888   GNode *saiz_node, *saio_node, *pssh_node;
3889   GstByteReader saiz_data, saio_data;
3890   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3891   gint64 base_offset, running_offset;
3892   guint32 frag_num;
3893   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3894
3895   /* NOTE @stream ignored */
3896
3897   moof_node = g_node_new ((guint8 *) buffer);
3898   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3899   qtdemux_node_dump (qtdemux, moof_node);
3900
3901   /* Get fragment number from mfhd and check it's valid */
3902   mfhd_node =
3903       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3904   if (mfhd_node == NULL)
3905     goto missing_mfhd;
3906   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3907     goto fail;
3908   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3909
3910   /* unknown base_offset to start with */
3911   base_offset = running_offset = -1;
3912   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3913   while (traf_node) {
3914     guint64 decode_time = 0;
3915
3916     /* Fragment Header node */
3917     tfhd_node =
3918         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3919         &tfhd_data);
3920     if (!tfhd_node)
3921       goto missing_tfhd;
3922     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3923             &ds_size, &ds_flags, &base_offset))
3924       goto missing_tfhd;
3925
3926     /* The following code assumes at most a single set of sample auxiliary
3927      * data in the fragment (consisting of a saiz box and a corresponding saio
3928      * box); in theory, however, there could be multiple sets of sample
3929      * auxiliary data in a fragment. */
3930     saiz_node =
3931         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3932         &saiz_data);
3933     if (saiz_node) {
3934       guint32 info_type = 0;
3935       guint64 offset = 0;
3936       guint32 info_type_parameter = 0;
3937
3938       g_free (qtdemux->cenc_aux_info_sizes);
3939
3940       qtdemux->cenc_aux_info_sizes =
3941           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3942           &qtdemux->cenc_aux_sample_count);
3943       if (qtdemux->cenc_aux_info_sizes == NULL) {
3944         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3945         goto fail;
3946       }
3947       saio_node =
3948           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3949           &saio_data);
3950       if (!saio_node) {
3951         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3952         g_free (qtdemux->cenc_aux_info_sizes);
3953         qtdemux->cenc_aux_info_sizes = NULL;
3954         goto fail;
3955       }
3956
3957       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3958                   &info_type, &info_type_parameter, &offset))) {
3959         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3960         g_free (qtdemux->cenc_aux_info_sizes);
3961         qtdemux->cenc_aux_info_sizes = NULL;
3962         goto fail;
3963       }
3964       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3965         offset += (guint64) (base_offset - qtdemux->moof_offset);
3966       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3967         GstByteReader br;
3968         if (offset > length) {
3969           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3970           qtdemux->cenc_aux_info_offset = offset;
3971         } else {
3972           gst_byte_reader_init (&br, buffer + offset, length - offset);
3973           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3974                   qtdemux->cenc_aux_info_sizes,
3975                   qtdemux->cenc_aux_sample_count)) {
3976             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3977             g_free (qtdemux->cenc_aux_info_sizes);
3978             qtdemux->cenc_aux_info_sizes = NULL;
3979             goto fail;
3980           }
3981         }
3982       }
3983     }
3984
3985     tfdt_node =
3986         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3987         &tfdt_data);
3988     if (tfdt_node) {
3989       /* We'll use decode_time to interpolate timestamps
3990        * in case the input timestamps are missing */
3991       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3992
3993       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3994           " (%" GST_TIME_FORMAT ")", decode_time,
3995           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3996                   decode_time) : GST_CLOCK_TIME_NONE));
3997
3998       /* Discard the fragment buffer timestamp info to avoid using it.
3999        * Rely on tfdt instead as it is more accurate than the timestamp
4000        * that is fetched from a manifest/playlist and is usually
4001        * less accurate. */
4002       qtdemux->fragment_start = -1;
4003     }
4004
4005     if (G_UNLIKELY (!stream)) {
4006       /* we lost track of offset, we'll need to regain it,
4007        * but can delay complaining until later or avoid doing so altogether */
4008       base_offset = -2;
4009       goto next;
4010     }
4011     if (G_UNLIKELY (base_offset < -1))
4012       goto lost_offset;
4013
4014     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4015
4016     if (!qtdemux->pullbased) {
4017       /* Sample tables can grow enough to be problematic if the system memory
4018        * is very low (e.g. embedded devices) and the videos very long
4019        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4020        * Fortunately, we can easily discard them for each new fragment when
4021        * we know qtdemux will not receive seeks outside of the current fragment.
4022        * adaptivedemux honors this assumption.
4023        * This optimization is also useful for applications that use qtdemux as
4024        * a push-based simple demuxer, like Media Source Extensions. */
4025       gst_qtdemux_stream_flush_samples_data (stream);
4026     }
4027
4028     /* initialise moof sample data */
4029     stream->n_samples_moof = 0;
4030     stream->duration_last_moof = stream->duration_moof;
4031     stream->duration_moof = 0;
4032
4033     /* Track Run node */
4034     trun_node =
4035         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4036         &trun_data);
4037     while (trun_node) {
4038       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4039           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4040           &running_offset, decode_time, (tfdt_node != NULL));
4041       /* iterate all siblings */
4042       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4043           &trun_data);
4044     }
4045
4046     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4047     if (uuid_node) {
4048       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4049       guint32 box_length = QT_UINT32 (uuid_buffer);
4050
4051       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4052     }
4053
4054     /* if no new base_offset provided for next traf,
4055      * base is end of current traf */
4056     base_offset = running_offset;
4057     running_offset = -1;
4058
4059     if (stream->n_samples_moof && stream->duration_moof)
4060       stream->new_caps = TRUE;
4061
4062   next:
4063     /* iterate all siblings */
4064     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4065   }
4066
4067   /* parse any protection system info */
4068   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4069   while (pssh_node) {
4070     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4071     qtdemux_parse_pssh (qtdemux, pssh_node);
4072     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4073   }
4074
4075   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4076       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4077       && min_dts != 0) {
4078     /* Unless the user has explicitly requested another seek, perform an
4079      * internal seek to the time specified in the tfdt.
4080      *
4081      * This way if the user opens a file where the first tfdt is 1 hour
4082      * into the presentation, they will not have to wait 1 hour for run
4083      * time to catch up and actual playback to start. */
4084     gint i;
4085
4086     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4087         "performing an internal seek to %" GST_TIME_FORMAT,
4088         GST_TIME_ARGS (min_dts));
4089
4090     qtdemux->segment.start = min_dts;
4091     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4092
4093     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4094       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4095       stream->time_position = min_dts;
4096     }
4097
4098     /* Before this code was run a segment was already sent when the moov was
4099      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4100      * be emitted after a moov, and we can emit a second segment anyway for
4101      * special cases like this. */
4102     qtdemux->need_segment = TRUE;
4103   }
4104
4105   qtdemux->first_moof_already_parsed = TRUE;
4106
4107   g_node_destroy (moof_node);
4108   return TRUE;
4109
4110 missing_tfhd:
4111   {
4112     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4113     goto fail;
4114   }
4115 missing_mfhd:
4116   {
4117     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4118     goto fail;
4119   }
4120 lost_offset:
4121   {
4122     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4123     goto fail;
4124   }
4125 fail:
4126   {
4127     g_node_destroy (moof_node);
4128     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4129         (_("This file is corrupt and cannot be played.")), (NULL));
4130     return FALSE;
4131   }
4132 }
4133
4134 #if 0
4135 /* might be used if some day we actually use mfra & co
4136  * for random access to fragments,
4137  * but that will require quite some modifications and much less relying
4138  * on a sample array */
4139 #endif
4140
4141 static gboolean
4142 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4143 {
4144   QtDemuxStream *stream;
4145   guint32 ver_flags, track_id, len, num_entries, i;
4146   guint value_size, traf_size, trun_size, sample_size;
4147   guint64 time = 0, moof_offset = 0;
4148 #if 0
4149   GstBuffer *buf = NULL;
4150   GstFlowReturn ret;
4151 #endif
4152   GstByteReader tfra;
4153
4154   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4155
4156   if (!gst_byte_reader_skip (&tfra, 8))
4157     return FALSE;
4158
4159   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4160     return FALSE;
4161
4162   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4163       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4164       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4165     return FALSE;
4166
4167   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4168
4169   stream = qtdemux_find_stream (qtdemux, track_id);
4170   if (stream == NULL)
4171     goto unknown_trackid;
4172
4173   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4174   sample_size = (len & 3) + 1;
4175   trun_size = ((len & 12) >> 2) + 1;
4176   traf_size = ((len & 48) >> 4) + 1;
4177
4178   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4179       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4180
4181   if (num_entries == 0)
4182     goto no_samples;
4183
4184   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4185           value_size + value_size + traf_size + trun_size + sample_size))
4186     goto corrupt_file;
4187
4188   g_free (stream->ra_entries);
4189   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4190   stream->n_ra_entries = num_entries;
4191
4192   for (i = 0; i < num_entries; i++) {
4193     qt_atom_parser_get_offset (&tfra, value_size, &time);
4194     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4195     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4196     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4197     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4198
4199     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4200
4201     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4202         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4203
4204     stream->ra_entries[i].ts = time;
4205     stream->ra_entries[i].moof_offset = moof_offset;
4206
4207     /* don't want to go through the entire file and read all moofs at startup */
4208 #if 0
4209     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4210     if (ret != GST_FLOW_OK)
4211       goto corrupt_file;
4212     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4213         moof_offset, stream);
4214     gst_buffer_unref (buf);
4215 #endif
4216   }
4217
4218   check_update_duration (qtdemux, time);
4219
4220   return TRUE;
4221
4222 /* ERRORS */
4223 unknown_trackid:
4224   {
4225     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4226     return FALSE;
4227   }
4228 corrupt_file:
4229   {
4230     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4231     return FALSE;
4232   }
4233 no_samples:
4234   {
4235     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4236     return FALSE;
4237   }
4238 }
4239
4240 static gboolean
4241 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4242 {
4243   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4244   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4245   GstBuffer *mfro = NULL, *mfra = NULL;
4246   GstFlowReturn flow;
4247   gboolean ret = FALSE;
4248   GNode *mfra_node, *tfra_node;
4249   guint64 mfra_offset = 0;
4250   guint32 fourcc, mfra_size;
4251   gint64 len;
4252
4253   /* query upstream size in bytes */
4254   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4255     goto size_query_failed;
4256
4257   /* mfro box should be at the very end of the file */
4258   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4259   if (flow != GST_FLOW_OK)
4260     goto exit;
4261
4262   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4263
4264   fourcc = QT_FOURCC (mfro_map.data + 4);
4265   if (fourcc != FOURCC_mfro)
4266     goto exit;
4267
4268   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4269   if (mfro_map.size < 16)
4270     goto invalid_mfro_size;
4271
4272   mfra_size = QT_UINT32 (mfro_map.data + 12);
4273   if (mfra_size >= len)
4274     goto invalid_mfra_size;
4275
4276   mfra_offset = len - mfra_size;
4277
4278   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4279       mfra_offset, mfra_size);
4280
4281   /* now get and parse mfra box */
4282   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4283   if (flow != GST_FLOW_OK)
4284     goto broken_file;
4285
4286   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4287
4288   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4289   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4290
4291   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4292
4293   while (tfra_node) {
4294     qtdemux_parse_tfra (qtdemux, tfra_node);
4295     /* iterate all siblings */
4296     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4297   }
4298   g_node_destroy (mfra_node);
4299
4300   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4301   ret = TRUE;
4302
4303 exit:
4304
4305   if (mfro) {
4306     if (mfro_map.memory != NULL)
4307       gst_buffer_unmap (mfro, &mfro_map);
4308     gst_buffer_unref (mfro);
4309   }
4310   if (mfra) {
4311     if (mfra_map.memory != NULL)
4312       gst_buffer_unmap (mfra, &mfra_map);
4313     gst_buffer_unref (mfra);
4314   }
4315   return ret;
4316
4317 /* ERRORS */
4318 size_query_failed:
4319   {
4320     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4321     goto exit;
4322   }
4323 invalid_mfro_size:
4324   {
4325     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4326     goto exit;
4327   }
4328 invalid_mfra_size:
4329   {
4330     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4331     goto exit;
4332   }
4333 broken_file:
4334   {
4335     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4336     goto exit;
4337   }
4338 }
4339
4340 static guint64
4341 add_offset (guint64 offset, guint64 advance)
4342 {
4343   /* Avoid 64-bit overflow by clamping */
4344   if (offset > G_MAXUINT64 - advance)
4345     return G_MAXUINT64;
4346   return offset + advance;
4347 }
4348
4349 static GstFlowReturn
4350 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4351 {
4352   guint64 length = 0;
4353   guint32 fourcc = 0;
4354   GstBuffer *buf = NULL;
4355   GstFlowReturn ret = GST_FLOW_OK;
4356   guint64 cur_offset = qtdemux->offset;
4357   GstMapInfo map;
4358
4359   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4360   if (G_UNLIKELY (ret != GST_FLOW_OK))
4361     goto beach;
4362   gst_buffer_map (buf, &map, GST_MAP_READ);
4363   if (G_LIKELY (map.size >= 8))
4364     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4365   gst_buffer_unmap (buf, &map);
4366   gst_buffer_unref (buf);
4367
4368   /* maybe we already got most we needed, so only consider this eof */
4369   if (G_UNLIKELY (length == 0)) {
4370     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4371         (_("Invalid atom size.")),
4372         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4373             GST_FOURCC_ARGS (fourcc)));
4374     ret = GST_FLOW_EOS;
4375     goto beach;
4376   }
4377
4378   switch (fourcc) {
4379     case FOURCC_moof:
4380       /* record for later parsing when needed */
4381       if (!qtdemux->moof_offset) {
4382         qtdemux->moof_offset = qtdemux->offset;
4383       }
4384       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4385         /* FIXME */
4386       } else {
4387         qtdemux->offset += length;      /* skip moof and keep going */
4388       }
4389       if (qtdemux->got_moov) {
4390         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4391         ret = GST_FLOW_EOS;
4392         goto beach;
4393       }
4394       break;
4395     case FOURCC_mdat:
4396     case FOURCC_free:
4397     case FOURCC_skip:
4398     case FOURCC_wide:
4399     case FOURCC_PICT:
4400     case FOURCC_pnot:
4401     {
4402       GST_LOG_OBJECT (qtdemux,
4403           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4404           GST_FOURCC_ARGS (fourcc), cur_offset);
4405       qtdemux->offset = add_offset (qtdemux->offset, length);
4406       break;
4407     }
4408     case FOURCC_moov:
4409     {
4410       GstBuffer *moov = NULL;
4411
4412       if (qtdemux->got_moov) {
4413         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4414         qtdemux->offset = add_offset (qtdemux->offset, length);
4415         goto beach;
4416       }
4417
4418       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4419       if (ret != GST_FLOW_OK)
4420         goto beach;
4421       gst_buffer_map (moov, &map, GST_MAP_READ);
4422
4423       if (length != map.size) {
4424         /* Some files have a 'moov' atom at the end of the file which contains
4425          * a terminal 'free' atom where the body of the atom is missing.
4426          * Check for, and permit, this special case.
4427          */
4428         if (map.size >= 8) {
4429           guint8 *final_data = map.data + (map.size - 8);
4430           guint32 final_length = QT_UINT32 (final_data);
4431           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4432
4433           if (final_fourcc == FOURCC_free
4434               && map.size + final_length - 8 == length) {
4435             /* Ok, we've found that special case. Allocate a new buffer with
4436              * that free atom actually present. */
4437             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4438             gst_buffer_fill (newmoov, 0, map.data, map.size);
4439             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4440             gst_buffer_unmap (moov, &map);
4441             gst_buffer_unref (moov);
4442             moov = newmoov;
4443             gst_buffer_map (moov, &map, GST_MAP_READ);
4444           }
4445         }
4446       }
4447
4448       if (length != map.size) {
4449         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4450             (_("This file is incomplete and cannot be played.")),
4451             ("We got less than expected (received %" G_GSIZE_FORMAT
4452                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4453                 (guint) length, cur_offset));
4454         gst_buffer_unmap (moov, &map);
4455         gst_buffer_unref (moov);
4456         ret = GST_FLOW_ERROR;
4457         goto beach;
4458       }
4459       qtdemux->offset += length;
4460
4461       qtdemux_parse_moov (qtdemux, map.data, length);
4462       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4463
4464       qtdemux_parse_tree (qtdemux);
4465       if (qtdemux->moov_node_compressed) {
4466         g_node_destroy (qtdemux->moov_node_compressed);
4467         g_free (qtdemux->moov_node->data);
4468       }
4469       qtdemux->moov_node_compressed = NULL;
4470       g_node_destroy (qtdemux->moov_node);
4471       qtdemux->moov_node = NULL;
4472       gst_buffer_unmap (moov, &map);
4473       gst_buffer_unref (moov);
4474       qtdemux->got_moov = TRUE;
4475
4476       break;
4477     }
4478     case FOURCC_ftyp:
4479     {
4480       GstBuffer *ftyp = NULL;
4481
4482       /* extract major brand; might come in handy for ISO vs QT issues */
4483       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4484       if (ret != GST_FLOW_OK)
4485         goto beach;
4486       qtdemux->offset += length;
4487       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4488       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4489       gst_buffer_unmap (ftyp, &map);
4490       gst_buffer_unref (ftyp);
4491       break;
4492     }
4493     case FOURCC_uuid:
4494     {
4495       GstBuffer *uuid = NULL;
4496
4497       /* uuid are extension atoms */
4498       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4499       if (ret != GST_FLOW_OK)
4500         goto beach;
4501       qtdemux->offset += length;
4502       gst_buffer_map (uuid, &map, GST_MAP_READ);
4503       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4504       gst_buffer_unmap (uuid, &map);
4505       gst_buffer_unref (uuid);
4506       break;
4507     }
4508     case FOURCC_sidx:
4509     {
4510       GstBuffer *sidx = NULL;
4511       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4512       if (ret != GST_FLOW_OK)
4513         goto beach;
4514       qtdemux->offset += length;
4515       gst_buffer_map (sidx, &map, GST_MAP_READ);
4516       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4517       gst_buffer_unmap (sidx, &map);
4518       gst_buffer_unref (sidx);
4519       break;
4520     }
4521     default:
4522     {
4523       GstBuffer *unknown = NULL;
4524
4525       GST_LOG_OBJECT (qtdemux,
4526           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4527           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4528           cur_offset);
4529       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4530       if (ret != GST_FLOW_OK)
4531         goto beach;
4532       gst_buffer_map (unknown, &map, GST_MAP_READ);
4533       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4534       gst_buffer_unmap (unknown, &map);
4535       gst_buffer_unref (unknown);
4536       qtdemux->offset += length;
4537       break;
4538     }
4539   }
4540
4541 beach:
4542   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4543     /* digested all data, show what we have */
4544     qtdemux_prepare_streams (qtdemux);
4545     QTDEMUX_EXPOSE_LOCK (qtdemux);
4546     ret = qtdemux_expose_streams (qtdemux);
4547     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4548
4549     qtdemux->state = QTDEMUX_STATE_MOVIE;
4550     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4551         qtdemux->state);
4552     return ret;
4553   }
4554   return ret;
4555 }
4556
4557 /* Seeks to the previous keyframe of the indexed stream and
4558  * aligns other streams with respect to the keyframe timestamp
4559  * of indexed stream. Only called in case of Reverse Playback
4560  */
4561 static GstFlowReturn
4562 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4563 {
4564   guint32 seg_idx = 0, k_index = 0;
4565   guint32 ref_seg_idx, ref_k_index;
4566   GstClockTime k_pos = 0, last_stop = 0;
4567   QtDemuxSegment *seg = NULL;
4568   QtDemuxStream *ref_str = NULL;
4569   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4570   guint64 target_ts;
4571   gint i;
4572
4573   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4574    * and finally align all the other streams on that timestamp with their
4575    * respective keyframes */
4576   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4577     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4578
4579     /* No candidate yet, take the first stream */
4580     if (!ref_str) {
4581       ref_str = str;
4582       continue;
4583     }
4584
4585     /* So that stream has a segment, we prefer video streams */
4586     if (str->subtype == FOURCC_vide) {
4587       ref_str = str;
4588       break;
4589     }
4590   }
4591
4592   if (G_UNLIKELY (!ref_str)) {
4593     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4594     goto eos;
4595   }
4596
4597   if (G_UNLIKELY (!ref_str->from_sample)) {
4598     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4599     goto eos;
4600   }
4601
4602   /* So that stream has been playing from from_sample to to_sample. We will
4603    * get the timestamp of the previous sample and search for a keyframe before
4604    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4605   if (ref_str->subtype == FOURCC_vide) {
4606     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4607         ref_str->from_sample - 1, FALSE);
4608   } else {
4609     if (ref_str->from_sample >= 10)
4610       k_index = ref_str->from_sample - 10;
4611     else
4612       k_index = 0;
4613   }
4614
4615   target_ts =
4616       ref_str->samples[k_index].timestamp +
4617       ref_str->samples[k_index].pts_offset;
4618
4619   /* get current segment for that stream */
4620   seg = &ref_str->segments[ref_str->segment_index];
4621   /* Use segment start in original timescale for comparisons */
4622   seg_media_start_mov = seg->trak_media_start;
4623
4624   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4625       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4626       k_index, target_ts, seg_media_start_mov,
4627       GST_TIME_ARGS (seg->media_start));
4628
4629   /* Crawl back through segments to find the one containing this I frame */
4630   while (target_ts < seg_media_start_mov) {
4631     GST_DEBUG_OBJECT (qtdemux,
4632         "keyframe position (sample %u) is out of segment %u " " target %"
4633         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4634         ref_str->segment_index, target_ts, seg_media_start_mov);
4635
4636     if (G_UNLIKELY (!ref_str->segment_index)) {
4637       /* Reached first segment, let's consider it's EOS */
4638       goto eos;
4639     }
4640     ref_str->segment_index--;
4641     seg = &ref_str->segments[ref_str->segment_index];
4642     /* Use segment start in original timescale for comparisons */
4643     seg_media_start_mov = seg->trak_media_start;
4644   }
4645   /* Calculate time position of the keyframe and where we should stop */
4646   k_pos =
4647       QTSTREAMTIME_TO_GSTTIME (ref_str,
4648       target_ts - seg->trak_media_start) + seg->time;
4649   last_stop =
4650       QTSTREAMTIME_TO_GSTTIME (ref_str,
4651       ref_str->samples[ref_str->from_sample].timestamp -
4652       seg->trak_media_start) + seg->time;
4653
4654   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4655       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4656       k_index, GST_TIME_ARGS (k_pos));
4657
4658   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4659   qtdemux->segment.position = last_stop;
4660   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4661       GST_TIME_ARGS (last_stop));
4662
4663   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4664     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4665     goto eos;
4666   }
4667
4668   ref_seg_idx = ref_str->segment_index;
4669   ref_k_index = k_index;
4670
4671   /* Align them all on this */
4672   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4673     guint32 index = 0;
4674     GstClockTime seg_time = 0;
4675     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4676
4677     /* aligning reference stream again might lead to backing up to yet another
4678      * keyframe (due to timestamp rounding issues),
4679      * potentially putting more load on downstream; so let's try to avoid */
4680     if (str == ref_str) {
4681       seg_idx = ref_seg_idx;
4682       seg = &str->segments[seg_idx];
4683       k_index = ref_k_index;
4684       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4685           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4686     } else {
4687       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4688       GST_DEBUG_OBJECT (qtdemux,
4689           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4690           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4691
4692       /* get segment and time in the segment */
4693       seg = &str->segments[seg_idx];
4694       seg_time = k_pos - seg->time;
4695
4696       /* get the media time in the segment.
4697        * No adjustment for empty "filler" segments */
4698       if (seg->media_start != GST_CLOCK_TIME_NONE)
4699         seg_time += seg->media_start;
4700
4701       /* get the index of the sample with media time */
4702       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4703       GST_DEBUG_OBJECT (qtdemux,
4704           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4705           GST_TIME_ARGS (seg_time), index);
4706
4707       /* find previous keyframe */
4708       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4709     }
4710
4711     /* Remember until where we want to go */
4712     str->to_sample = str->from_sample - 1;
4713     /* Define our time position */
4714     target_ts =
4715         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4716     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4717     if (seg->media_start != GST_CLOCK_TIME_NONE)
4718       str->time_position -= seg->media_start;
4719
4720     /* Now seek back in time */
4721     gst_qtdemux_move_stream (qtdemux, str, k_index);
4722     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4723         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4724         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4725   }
4726
4727   return GST_FLOW_OK;
4728
4729 eos:
4730   return GST_FLOW_EOS;
4731 }
4732
4733 /*
4734  * Gets the current qt segment start, stop and position for the
4735  * given time offset. This is used in update_segment()
4736  */
4737 static void
4738 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4739     QtDemuxStream * stream, GstClockTime offset,
4740     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4741 {
4742   GstClockTime seg_time;
4743   GstClockTime start, stop, time;
4744   QtDemuxSegment *segment;
4745
4746   segment = &stream->segments[stream->segment_index];
4747
4748   /* get time in this segment */
4749   seg_time = (offset - segment->time) * segment->rate;
4750
4751   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4752       GST_TIME_ARGS (seg_time));
4753
4754   if (G_UNLIKELY (seg_time > segment->duration)) {
4755     GST_LOG_OBJECT (stream->pad,
4756         "seg_time > segment->duration %" GST_TIME_FORMAT,
4757         GST_TIME_ARGS (segment->duration));
4758     seg_time = segment->duration;
4759   }
4760
4761   /* qtdemux->segment.stop is in outside-time-realm, whereas
4762    * segment->media_stop is in track-time-realm.
4763    *
4764    * In order to compare the two, we need to bring segment.stop
4765    * into the track-time-realm
4766    *
4767    * FIXME - does this comment still hold? Don't see any conversion here */
4768
4769   stop = qtdemux->segment.stop;
4770   if (stop == GST_CLOCK_TIME_NONE)
4771     stop = qtdemux->segment.duration;
4772   if (stop == GST_CLOCK_TIME_NONE)
4773     stop = segment->media_stop;
4774   else
4775     stop =
4776         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4777
4778   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4779     start = segment->time + seg_time;
4780     time = offset;
4781     stop = start - seg_time + segment->duration;
4782   } else if (qtdemux->segment.rate >= 0) {
4783     start = MIN (segment->media_start + seg_time, stop);
4784     time = offset;
4785   } else {
4786     if (segment->media_start >= qtdemux->segment.start) {
4787       time = segment->time;
4788     } else {
4789       time = segment->time + (qtdemux->segment.start - segment->media_start);
4790     }
4791
4792     start = MAX (segment->media_start, qtdemux->segment.start);
4793     stop = MIN (segment->media_start + seg_time, stop);
4794   }
4795
4796   *_start = start;
4797   *_stop = stop;
4798   *_time = time;
4799 }
4800
4801 /*
4802  * Updates the qt segment used for the stream and pushes a new segment event
4803  * downstream on this stream's pad.
4804  */
4805 static gboolean
4806 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4807     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4808     GstClockTime * _stop)
4809 {
4810   QtDemuxSegment *segment;
4811   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4812   gdouble rate;
4813   GstEvent *event;
4814
4815   /* update the current segment */
4816   stream->segment_index = seg_idx;
4817
4818   /* get the segment */
4819   segment = &stream->segments[seg_idx];
4820
4821   if (G_UNLIKELY (offset < segment->time)) {
4822     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4823         GST_TIME_ARGS (segment->time));
4824     return FALSE;
4825   }
4826
4827   /* segment lies beyond total indicated duration */
4828   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4829           segment->time > qtdemux->segment.duration)) {
4830     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4831         " < segment->time %" GST_TIME_FORMAT,
4832         GST_TIME_ARGS (qtdemux->segment.duration),
4833         GST_TIME_ARGS (segment->time));
4834     return FALSE;
4835   }
4836
4837   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4838       &start, &stop, &time);
4839
4840   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4841       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4842       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4843
4844   /* combine global rate with that of the segment */
4845   rate = segment->rate * qtdemux->segment.rate;
4846
4847   /* Copy flags from main segment */
4848   stream->segment.flags = qtdemux->segment.flags;
4849
4850   /* update the segment values used for clipping */
4851   stream->segment.offset = qtdemux->segment.offset;
4852   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4853   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4854   stream->segment.rate = rate;
4855   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4856       stream->cslg_shift);
4857   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4858       stream->cslg_shift);
4859   stream->segment.time = time;
4860   stream->segment.position = stream->segment.start;
4861
4862   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4863       &stream->segment);
4864
4865   /* now prepare and send the segment */
4866   if (stream->pad) {
4867     event = gst_event_new_segment (&stream->segment);
4868     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4869       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4870     }
4871     gst_pad_push_event (stream->pad, event);
4872     /* assume we can send more data now */
4873     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4874     /* clear to send tags on this pad now */
4875     gst_qtdemux_push_tags (qtdemux, stream);
4876   }
4877
4878   if (_start)
4879     *_start = start;
4880   if (_stop)
4881     *_stop = stop;
4882
4883   return TRUE;
4884 }
4885
4886 /* activate the given segment number @seg_idx of @stream at time @offset.
4887  * @offset is an absolute global position over all the segments.
4888  *
4889  * This will push out a NEWSEGMENT event with the right values and
4890  * position the stream index to the first decodable sample before
4891  * @offset.
4892  */
4893 static gboolean
4894 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4895     guint32 seg_idx, GstClockTime offset)
4896 {
4897   QtDemuxSegment *segment;
4898   guint32 index, kf_index;
4899   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4900
4901   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4902       seg_idx, GST_TIME_ARGS (offset));
4903
4904   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4905           &start, &stop))
4906     return FALSE;
4907
4908   segment = &stream->segments[stream->segment_index];
4909
4910   /* in the fragmented case, we pick a fragment that starts before our
4911    * desired position and rely on downstream to wait for a keyframe
4912    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4913    * tfra entries tells us which trun/sample the key unit is in, but we don't
4914    * make use of this additional information at the moment) */
4915   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4916     stream->to_sample = G_MAXUINT32;
4917     return TRUE;
4918   } else {
4919     /* well, it will be taken care of below */
4920     qtdemux->fragmented_seek_pending = FALSE;
4921     /* FIXME ideally the do_fragmented_seek can be done right here,
4922      * rather than at loop level
4923      * (which might even allow handling edit lists in a fragmented file) */
4924   }
4925
4926   /* We don't need to look for a sample in push-based */
4927   if (!qtdemux->pullbased)
4928     return TRUE;
4929
4930   /* and move to the keyframe before the indicated media time of the
4931    * segment */
4932   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4933     if (qtdemux->segment.rate >= 0) {
4934       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4935       stream->to_sample = G_MAXUINT32;
4936       GST_DEBUG_OBJECT (stream->pad,
4937           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4938           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4939           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4940     } else {
4941       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4942       stream->to_sample = index;
4943       GST_DEBUG_OBJECT (stream->pad,
4944           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4945           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4946           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4947     }
4948   } else {
4949     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4950         "this is an empty segment");
4951     return TRUE;
4952   }
4953
4954   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4955    * encountered an error and printed a message so we return appropriately */
4956   if (index == -1)
4957     return FALSE;
4958
4959   /* we're at the right spot */
4960   if (index == stream->sample_index) {
4961     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4962     return TRUE;
4963   }
4964
4965   /* find keyframe of the target index */
4966   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4967
4968   /* go back two frames to provide lead-in for non-raw audio decoders */
4969   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
4970     guint32 lead_in = 2;
4971     guint32 old_index = kf_index;
4972     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
4973
4974     if (gst_structure_has_name (s, "audio/mpeg")) {
4975       gint mpegversion;
4976       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
4977           && mpegversion == 1) {
4978         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
4979         lead_in = 30;
4980       }
4981     }
4982
4983     kf_index = MAX (kf_index, lead_in) - lead_in;
4984     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
4985       GST_DEBUG_OBJECT (stream->pad,
4986           "Moving backwards %u frames to ensure sufficient sound lead-in",
4987           old_index - kf_index);
4988     } else {
4989       kf_index = old_index;
4990     }
4991   }
4992
4993   /* if we move forwards, we don't have to go back to the previous
4994    * keyframe since we already sent that. We can also just jump to
4995    * the keyframe right before the target index if there is one. */
4996   if (index > stream->sample_index) {
4997     /* moving forwards check if we move past a keyframe */
4998     if (kf_index > stream->sample_index) {
4999       GST_DEBUG_OBJECT (stream->pad,
5000           "moving forwards to keyframe at %u "
5001           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5002           kf_index,
5003           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5004           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5005       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5006     } else {
5007       GST_DEBUG_OBJECT (stream->pad,
5008           "moving forwards, keyframe at %u "
5009           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5010           kf_index,
5011           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5012           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5013     }
5014   } else {
5015     GST_DEBUG_OBJECT (stream->pad,
5016         "moving backwards to %sframe at %u "
5017         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5018         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5019         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5020         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5021     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5022   }
5023
5024   return TRUE;
5025 }
5026
5027 /* prepare to get the current sample of @stream, getting essential values.
5028  *
5029  * This function will also prepare and send the segment when needed.
5030  *
5031  * Return FALSE if the stream is EOS.
5032  *
5033  * PULL-BASED
5034  */
5035 static gboolean
5036 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5037     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5038     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5039     gboolean * keyframe)
5040 {
5041   QtDemuxSample *sample;
5042   GstClockTime time_position;
5043   guint32 seg_idx;
5044
5045   g_return_val_if_fail (stream != NULL, FALSE);
5046
5047   time_position = stream->time_position;
5048   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5049     goto eos;
5050
5051   seg_idx = stream->segment_index;
5052   if (G_UNLIKELY (seg_idx == -1)) {
5053     /* find segment corresponding to time_position if we are looking
5054      * for a segment. */
5055     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5056   }
5057
5058   /* different segment, activate it, sample_index will be set. */
5059   if (G_UNLIKELY (stream->segment_index != seg_idx))
5060     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5061
5062   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5063               segments[stream->segment_index]))) {
5064     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5065
5066     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5067         " prepare empty sample");
5068
5069     *empty = TRUE;
5070     *pts = *dts = time_position;
5071     *duration = seg->duration - (time_position - seg->time);
5072
5073     return TRUE;
5074   }
5075
5076   *empty = FALSE;
5077
5078   if (stream->sample_index == -1)
5079     stream->sample_index = 0;
5080
5081   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5082       stream->sample_index, stream->n_samples);
5083
5084   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5085     if (!qtdemux->fragmented)
5086       goto eos;
5087
5088     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5089     do {
5090       GstFlowReturn flow;
5091
5092       GST_OBJECT_LOCK (qtdemux);
5093       flow = qtdemux_add_fragmented_samples (qtdemux);
5094       GST_OBJECT_UNLOCK (qtdemux);
5095
5096       if (flow != GST_FLOW_OK)
5097         goto eos;
5098     }
5099     while (stream->sample_index >= stream->n_samples);
5100   }
5101
5102   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5103     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5104         stream->sample_index);
5105     return FALSE;
5106   }
5107
5108   /* now get the info for the sample we're at */
5109   sample = &stream->samples[stream->sample_index];
5110
5111   *dts = QTSAMPLE_DTS (stream, sample);
5112   *pts = QTSAMPLE_PTS (stream, sample);
5113   *offset = sample->offset;
5114   *size = sample->size;
5115   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5116   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5117
5118   return TRUE;
5119
5120   /* special cases */
5121 eos:
5122   {
5123     stream->time_position = GST_CLOCK_TIME_NONE;
5124     return FALSE;
5125   }
5126 }
5127
5128 /* move to the next sample in @stream.
5129  *
5130  * Moves to the next segment when needed.
5131  */
5132 static void
5133 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5134 {
5135   QtDemuxSample *sample;
5136   QtDemuxSegment *segment;
5137
5138   /* get current segment */
5139   segment = &stream->segments[stream->segment_index];
5140
5141   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5142     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5143     goto next_segment;
5144   }
5145
5146   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5147     /* Mark the stream as EOS */
5148     GST_DEBUG_OBJECT (qtdemux,
5149         "reached max allowed sample %u, mark EOS", stream->to_sample);
5150     stream->time_position = GST_CLOCK_TIME_NONE;
5151     return;
5152   }
5153
5154   /* move to next sample */
5155   stream->sample_index++;
5156   stream->offset_in_sample = 0;
5157
5158   /* reached the last sample, we need the next segment */
5159   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5160     goto next_segment;
5161
5162   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5163     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5164         stream->sample_index);
5165     return;
5166   }
5167
5168   /* get next sample */
5169   sample = &stream->samples[stream->sample_index];
5170
5171   /* see if we are past the segment */
5172   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5173     goto next_segment;
5174
5175   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5176     /* inside the segment, update time_position, looks very familiar to
5177      * GStreamer segments, doesn't it? */
5178     stream->time_position =
5179         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5180   } else {
5181     /* not yet in segment, time does not yet increment. This means
5182      * that we are still prerolling keyframes to the decoder so it can
5183      * decode the first sample of the segment. */
5184     stream->time_position = segment->time;
5185   }
5186   return;
5187
5188   /* move to the next segment */
5189 next_segment:
5190   {
5191     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5192
5193     if (stream->segment_index == stream->n_segments - 1) {
5194       /* are we at the end of the last segment, we're EOS */
5195       stream->time_position = GST_CLOCK_TIME_NONE;
5196     } else {
5197       /* else we're only at the end of the current segment */
5198       stream->time_position = segment->stop_time;
5199     }
5200     /* make sure we select a new segment */
5201
5202     /* accumulate previous segments */
5203     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5204       stream->accumulated_base +=
5205           (stream->segment.stop -
5206           stream->segment.start) / ABS (stream->segment.rate);
5207
5208     stream->segment_index = -1;
5209   }
5210 }
5211
5212 static void
5213 gst_qtdemux_sync_streams (GstQTDemux * demux)
5214 {
5215   gint i;
5216
5217   if (QTDEMUX_N_STREAMS (demux) <= 1)
5218     return;
5219
5220   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5221     QtDemuxStream *stream;
5222     GstClockTime end_time;
5223
5224     stream = QTDEMUX_NTH_STREAM (demux, i);
5225
5226     if (!stream->pad)
5227       continue;
5228
5229     /* TODO advance time on subtitle streams here, if any some day */
5230
5231     /* some clips/trailers may have unbalanced streams at the end,
5232      * so send EOS on shorter stream to prevent stalling others */
5233
5234     /* do not mess with EOS if SEGMENT seeking */
5235     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5236       continue;
5237
5238     if (demux->pullbased) {
5239       /* loop mode is sample time based */
5240       if (!STREAM_IS_EOS (stream))
5241         continue;
5242     } else {
5243       /* push mode is byte position based */
5244       if (stream->n_samples &&
5245           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5246         continue;
5247     }
5248
5249     if (stream->sent_eos)
5250       continue;
5251
5252     /* only act if some gap */
5253     end_time = stream->segments[stream->n_segments - 1].stop_time;
5254     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5255         ", stream end: %" GST_TIME_FORMAT,
5256         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5257     if (GST_CLOCK_TIME_IS_VALID (end_time)
5258         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5259       GstEvent *event;
5260
5261       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5262           GST_PAD_NAME (stream->pad));
5263       stream->sent_eos = TRUE;
5264       event = gst_event_new_eos ();
5265       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5266         gst_event_set_seqnum (event, demux->segment_seqnum);
5267       gst_pad_push_event (stream->pad, event);
5268     }
5269   }
5270 }
5271
5272 /* EOS and NOT_LINKED need to be combined. This means that we return:
5273  *
5274  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5275  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5276  */
5277 static GstFlowReturn
5278 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5279     GstFlowReturn ret)
5280 {
5281   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5282
5283   if (stream->pad)
5284     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5285         ret);
5286   else
5287     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5288
5289   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5290   return ret;
5291 }
5292
5293 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5294  * completely clipped
5295  *
5296  * Should be used only with raw buffers */
5297 static GstBuffer *
5298 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5299     GstBuffer * buf)
5300 {
5301   guint64 start, stop, cstart, cstop, diff;
5302   GstClockTime pts, duration;
5303   gsize size, osize;
5304   gint num_rate, denom_rate;
5305   gint frame_size;
5306   gboolean clip_data;
5307   guint offset;
5308
5309   osize = size = gst_buffer_get_size (buf);
5310   offset = 0;
5311
5312   /* depending on the type, setup the clip parameters */
5313   if (stream->subtype == FOURCC_soun) {
5314     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5315     num_rate = GST_SECOND;
5316     denom_rate = (gint) CUR_STREAM (stream)->rate;
5317     clip_data = TRUE;
5318   } else if (stream->subtype == FOURCC_vide) {
5319     frame_size = size;
5320     num_rate = CUR_STREAM (stream)->fps_n;
5321     denom_rate = CUR_STREAM (stream)->fps_d;
5322     clip_data = FALSE;
5323   } else
5324     goto wrong_type;
5325
5326   if (frame_size <= 0)
5327     goto bad_frame_size;
5328
5329   /* we can only clip if we have a valid pts */
5330   pts = GST_BUFFER_PTS (buf);
5331   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5332     goto no_pts;
5333
5334   duration = GST_BUFFER_DURATION (buf);
5335
5336   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5337     duration =
5338         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5339   }
5340
5341   start = pts;
5342   stop = start + duration;
5343
5344   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5345               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5346     goto clipped;
5347
5348   /* see if some clipping happened */
5349   diff = cstart - start;
5350   if (diff > 0) {
5351     pts += diff;
5352     duration -= diff;
5353
5354     if (clip_data) {
5355       /* bring clipped time to samples and to bytes */
5356       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5357       diff *= frame_size;
5358
5359       GST_DEBUG_OBJECT (qtdemux,
5360           "clipping start to %" GST_TIME_FORMAT " %"
5361           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5362
5363       offset = diff;
5364       size -= diff;
5365     }
5366   }
5367   diff = stop - cstop;
5368   if (diff > 0) {
5369     duration -= diff;
5370
5371     if (clip_data) {
5372       /* bring clipped time to samples and then to bytes */
5373       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5374       diff *= frame_size;
5375       GST_DEBUG_OBJECT (qtdemux,
5376           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5377           " bytes", GST_TIME_ARGS (cstop), diff);
5378       size -= diff;
5379     }
5380   }
5381
5382   if (offset != 0 || size != osize)
5383     gst_buffer_resize (buf, offset, size);
5384
5385   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5386   GST_BUFFER_PTS (buf) = pts;
5387   GST_BUFFER_DURATION (buf) = duration;
5388
5389   return buf;
5390
5391   /* dropped buffer */
5392 wrong_type:
5393   {
5394     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5395     return buf;
5396   }
5397 bad_frame_size:
5398   {
5399     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5400     return buf;
5401   }
5402 no_pts:
5403   {
5404     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5405     return buf;
5406   }
5407 clipped:
5408   {
5409     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5410     gst_buffer_unref (buf);
5411     return NULL;
5412   }
5413 }
5414
5415 static GstBuffer *
5416 gst_qtdemux_align_buffer (GstQTDemux * demux,
5417     GstBuffer * buffer, gsize alignment)
5418 {
5419   GstMapInfo map;
5420
5421   gst_buffer_map (buffer, &map, GST_MAP_READ);
5422
5423   if (map.size < sizeof (guintptr)) {
5424     gst_buffer_unmap (buffer, &map);
5425     return buffer;
5426   }
5427
5428   if (((guintptr) map.data) & (alignment - 1)) {
5429     GstBuffer *new_buffer;
5430     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5431
5432     new_buffer = gst_buffer_new_allocate (NULL,
5433         gst_buffer_get_size (buffer), &params);
5434
5435     /* Copy data "by hand", so ensure alignment is kept: */
5436     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5437
5438     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5439     GST_DEBUG_OBJECT (demux,
5440         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5441         alignment);
5442
5443     gst_buffer_unmap (buffer, &map);
5444     gst_buffer_unref (buffer);
5445
5446     return new_buffer;
5447   }
5448
5449   gst_buffer_unmap (buffer, &map);
5450   return buffer;
5451 }
5452
5453 static guint8 *
5454 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5455     gsize * res)
5456 {
5457   guint8 *storage;
5458   gsize i;
5459
5460   /* We are converting from pairs to triplets */
5461   *res = ccpair_size / 2 * 3;
5462   storage = g_malloc (*res);
5463   for (i = 0; i * 2 < ccpair_size; i += 1) {
5464     /* FIXME: Use line offset 0 as we simply can't know here */
5465     if (field == 1)
5466       storage[i * 3] = 0x80 | 0x00;
5467     else
5468       storage[i * 3] = 0x00 | 0x00;
5469     storage[i * 3 + 1] = ccpair[i * 2];
5470     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5471   }
5472
5473   return storage;
5474 }
5475
5476 static guint8 *
5477 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5478     gsize * cclen)
5479 {
5480   guint8 *res = NULL;
5481   guint32 atom_length, fourcc;
5482   QtDemuxStreamStsdEntry *stsd_entry;
5483
5484   GST_MEMDUMP ("caption atom", data, size);
5485
5486   /* There might be multiple atoms */
5487
5488   *cclen = 0;
5489   if (size < 8)
5490     goto invalid_cdat;
5491   atom_length = QT_UINT32 (data);
5492   fourcc = QT_FOURCC (data + 4);
5493   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5494     goto invalid_cdat;
5495
5496   GST_DEBUG_OBJECT (stream->pad, "here");
5497
5498   /* Check if we have something compatible */
5499   stsd_entry = CUR_STREAM (stream);
5500   switch (stsd_entry->fourcc) {
5501     case FOURCC_c608:{
5502       guint8 *cdat = NULL, *cdt2 = NULL;
5503       gsize cdat_size = 0, cdt2_size = 0;
5504       /* Should be cdat or cdt2 */
5505       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5506         GST_WARNING_OBJECT (stream->pad,
5507             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5508             GST_FOURCC_ARGS (fourcc));
5509         goto invalid_cdat;
5510       }
5511
5512       /* Convert to S334-1 Annex A byte triplet */
5513       if (fourcc == FOURCC_cdat)
5514         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5515       else
5516         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5517       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5518           size, atom_length);
5519
5520       /* Check for another atom ? */
5521       if (size > atom_length + 8) {
5522         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5523         if (size >= atom_length + new_atom_length) {
5524           fourcc = QT_FOURCC (data + atom_length + 4);
5525           if (fourcc == FOURCC_cdat) {
5526             if (cdat == NULL)
5527               cdat =
5528                   convert_to_s334_1a (data + atom_length + 8,
5529                   new_atom_length - 8, 1, &cdat_size);
5530             else
5531               GST_WARNING_OBJECT (stream->pad,
5532                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5533           } else {
5534             if (cdt2 == NULL)
5535               cdt2 =
5536                   convert_to_s334_1a (data + atom_length + 8,
5537                   new_atom_length - 8, 2, &cdt2_size);
5538             else
5539               GST_WARNING_OBJECT (stream->pad,
5540                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5541           }
5542         }
5543       }
5544
5545       *cclen = cdat_size + cdt2_size;
5546       res = g_malloc (*cclen);
5547       if (cdat_size)
5548         memcpy (res, cdat, cdat_size);
5549       if (cdt2_size)
5550         memcpy (res + cdat_size, cdt2, cdt2_size);
5551       g_free (cdat);
5552       g_free (cdt2);
5553     }
5554       break;
5555     case FOURCC_c708:
5556       if (fourcc != FOURCC_ccdp) {
5557         GST_WARNING_OBJECT (stream->pad,
5558             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5559             GST_FOURCC_ARGS (fourcc));
5560         goto invalid_cdat;
5561       }
5562       *cclen = atom_length - 8;
5563       res = g_memdup (data + 8, *cclen);
5564       break;
5565     default:
5566       /* Keep this here in case other closed caption formats are added */
5567       g_assert_not_reached ();
5568       break;
5569   }
5570
5571   GST_MEMDUMP ("Output", res, *cclen);
5572   return res;
5573
5574   /* Errors */
5575 invalid_cdat:
5576   GST_WARNING ("[cdat] atom is too small or invalid");
5577   return NULL;
5578 }
5579
5580 /* the input buffer metadata must be writable,
5581  * but time/duration etc not yet set and need not be preserved */
5582 static GstBuffer *
5583 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5584     GstBuffer * buf)
5585 {
5586   GstMapInfo map;
5587   guint nsize = 0;
5588   gchar *str;
5589
5590   /* not many cases for now */
5591   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5592     /* send a one time dvd clut event */
5593     if (stream->pending_event && stream->pad)
5594       gst_pad_push_event (stream->pad, stream->pending_event);
5595     stream->pending_event = NULL;
5596   }
5597
5598   if (G_UNLIKELY (stream->subtype != FOURCC_text
5599           && stream->subtype != FOURCC_sbtl &&
5600           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5601     return buf;
5602   }
5603
5604   gst_buffer_map (buf, &map, GST_MAP_READ);
5605
5606   /* empty buffer is sent to terminate previous subtitle */
5607   if (map.size <= 2) {
5608     gst_buffer_unmap (buf, &map);
5609     gst_buffer_unref (buf);
5610     return NULL;
5611   }
5612   if (stream->subtype == FOURCC_subp) {
5613     /* That's all the processing needed for subpictures */
5614     gst_buffer_unmap (buf, &map);
5615     return buf;
5616   }
5617
5618   if (stream->subtype == FOURCC_clcp) {
5619     guint8 *cc;
5620     gsize cclen = 0;
5621     /* For closed caption, we need to extract the information from the
5622      * [cdat],[cdt2] or [ccdp] atom */
5623     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5624     gst_buffer_unmap (buf, &map);
5625     gst_buffer_unref (buf);
5626     if (cc) {
5627       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5628     } else {
5629       /* Conversion failed or there's nothing */
5630       buf = NULL;
5631     }
5632     return buf;
5633   }
5634
5635   nsize = GST_READ_UINT16_BE (map.data);
5636   nsize = MIN (nsize, map.size - 2);
5637
5638   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5639       nsize, map.size);
5640
5641   /* takes care of UTF-8 validation or UTF-16 recognition,
5642    * no other encoding expected */
5643   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5644   gst_buffer_unmap (buf, &map);
5645   if (str) {
5646     gst_buffer_unref (buf);
5647     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5648   } else {
5649     /* this should not really happen unless the subtitle is corrupted */
5650     gst_buffer_unref (buf);
5651     buf = NULL;
5652   }
5653
5654   /* FIXME ? convert optional subsequent style info to markup */
5655
5656   return buf;
5657 }
5658
5659 static GstFlowReturn
5660 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5661     GstBuffer * buf)
5662 {
5663   GstFlowReturn ret = GST_FLOW_OK;
5664   GstClockTime pts, duration;
5665
5666   if (stream->need_clip)
5667     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5668
5669   if (G_UNLIKELY (buf == NULL))
5670     goto exit;
5671
5672   if (G_UNLIKELY (stream->discont)) {
5673     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5674     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5675     stream->discont = FALSE;
5676   } else {
5677     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5678   }
5679
5680   GST_LOG_OBJECT (qtdemux,
5681       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5682       ", duration %" GST_TIME_FORMAT " on pad %s",
5683       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5684       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5685       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5686
5687   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5688     GstStructure *crypto_info;
5689     QtDemuxCencSampleSetInfo *info =
5690         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5691     gint index;
5692     GstEvent *event;
5693
5694     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5695       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5696           GST_PTR_FORMAT, event);
5697       gst_pad_push_event (stream->pad, event);
5698     }
5699
5700     if (info->crypto_info == NULL) {
5701       GST_DEBUG_OBJECT (qtdemux,
5702           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5703     } else {
5704       /* The end of the crypto_info array matches our n_samples position,
5705        * so count backward from there */
5706       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5707       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5708         /* steal structure from array */
5709         crypto_info = g_ptr_array_index (info->crypto_info, index);
5710         g_ptr_array_index (info->crypto_info, index) = NULL;
5711         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5712             info->crypto_info->len);
5713         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5714           GST_ERROR_OBJECT (qtdemux,
5715               "failed to attach cenc metadata to buffer");
5716       } else {
5717         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5718             index, stream->sample_index);
5719       }
5720     }
5721   }
5722
5723   if (stream->alignment > 1)
5724     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5725
5726   pts = GST_BUFFER_PTS (buf);
5727   duration = GST_BUFFER_DURATION (buf);
5728
5729   ret = gst_pad_push (stream->pad, buf);
5730
5731   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5732     /* mark position in stream, we'll need this to know when to send GAP event */
5733     stream->segment.position = pts + duration;
5734   }
5735
5736 exit:
5737
5738   return ret;
5739 }
5740
5741 static GstFlowReturn
5742 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5743     GstBuffer * buf)
5744 {
5745   GstFlowReturn ret = GST_FLOW_OK;
5746
5747   if (stream->subtype == FOURCC_clcp
5748       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5749     GstMapInfo map;
5750     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5751     guint n_triplets, i;
5752     guint field1_off = 0, field2_off = 0;
5753
5754     /* We have to split CEA608 buffers so that each outgoing buffer contains
5755      * one byte pair per field according to the framerate of the video track.
5756      *
5757      * If there is only a single byte pair per field we don't have to do
5758      * anything
5759      */
5760
5761     gst_buffer_map (buf, &map, GST_MAP_READ);
5762
5763     n_triplets = map.size / 3;
5764     for (i = 0; i < n_triplets; i++) {
5765       if (map.data[3 * i] & 0x80)
5766         n_field1++;
5767       else
5768         n_field2++;
5769     }
5770
5771     g_assert (n_field1 || n_field2);
5772
5773     /* If there's more than 1 frame we have to split, otherwise we can just
5774      * pass through */
5775     if (n_field1 > 1 || n_field2 > 1) {
5776       n_output_buffers =
5777           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5778           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5779
5780       for (i = 0; i < n_output_buffers; i++) {
5781         GstBuffer *outbuf =
5782             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5783         GstMapInfo outmap;
5784         guint8 *outptr;
5785
5786         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5787         outptr = outmap.data;
5788
5789         if (n_field1) {
5790           gboolean found = FALSE;
5791
5792           while (map.data + field1_off < map.data + map.size) {
5793             if (map.data[field1_off] & 0x80) {
5794               memcpy (outptr, &map.data[field1_off], 3);
5795               field1_off += 3;
5796               found = TRUE;
5797               break;
5798             }
5799             field1_off += 3;
5800           }
5801
5802           if (!found) {
5803             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5804
5805             memcpy (outptr, empty, 3);
5806           }
5807
5808           outptr += 3;
5809         }
5810
5811         if (n_field2) {
5812           gboolean found = FALSE;
5813
5814           while (map.data + field2_off < map.data + map.size) {
5815             if ((map.data[field2_off] & 0x80) == 0) {
5816               memcpy (outptr, &map.data[field2_off], 3);
5817               field2_off += 3;
5818               found = TRUE;
5819               break;
5820             }
5821             field2_off += 3;
5822           }
5823
5824           if (!found) {
5825             const guint8 empty[] = { 0x00, 0x80, 0x80 };
5826
5827             memcpy (outptr, empty, 3);
5828           }
5829
5830           outptr += 3;
5831         }
5832
5833         gst_buffer_unmap (outbuf, &outmap);
5834
5835         GST_BUFFER_PTS (outbuf) =
5836             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
5837             GST_SECOND * CUR_STREAM (stream)->fps_d,
5838             CUR_STREAM (stream)->fps_n);
5839         GST_BUFFER_DURATION (outbuf) =
5840             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
5841             CUR_STREAM (stream)->fps_n);
5842         GST_BUFFER_OFFSET (outbuf) = -1;
5843         GST_BUFFER_OFFSET_END (outbuf) = -1;
5844
5845         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
5846
5847         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
5848           break;
5849       }
5850       gst_buffer_unmap (buf, &map);
5851       gst_buffer_unref (buf);
5852     } else {
5853       gst_buffer_unmap (buf, &map);
5854       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5855     }
5856   } else {
5857     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
5858   }
5859
5860   return ret;
5861 }
5862
5863 /* Sets a buffer's attributes properly and pushes it downstream.
5864  * Also checks for additional actions and custom processing that may
5865  * need to be done first.
5866  */
5867 static GstFlowReturn
5868 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5869     QtDemuxStream * stream, GstBuffer * buf,
5870     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5871     gboolean keyframe, GstClockTime position, guint64 byte_position)
5872 {
5873   GstFlowReturn ret = GST_FLOW_OK;
5874
5875   /* offset the timestamps according to the edit list */
5876
5877   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5878     gchar *url;
5879     GstMapInfo map;
5880
5881     gst_buffer_map (buf, &map, GST_MAP_READ);
5882     url = g_strndup ((gchar *) map.data, map.size);
5883     gst_buffer_unmap (buf, &map);
5884     if (url != NULL && strlen (url) != 0) {
5885       /* we have RTSP redirect now */
5886       g_free (qtdemux->redirect_location);
5887       qtdemux->redirect_location = g_strdup (url);
5888       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5889           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5890               gst_structure_new ("redirect",
5891                   "new-location", G_TYPE_STRING, url, NULL)));
5892     } else {
5893       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5894           "posting");
5895     }
5896     g_free (url);
5897   }
5898
5899   /* position reporting */
5900   if (qtdemux->segment.rate >= 0) {
5901     qtdemux->segment.position = position;
5902     gst_qtdemux_sync_streams (qtdemux);
5903   }
5904
5905   if (G_UNLIKELY (!stream->pad)) {
5906     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5907     gst_buffer_unref (buf);
5908     goto exit;
5909   }
5910
5911   /* send out pending buffers */
5912   while (stream->buffers) {
5913     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5914
5915     if (G_UNLIKELY (stream->discont)) {
5916       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5917       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5918       stream->discont = FALSE;
5919     } else {
5920       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5921     }
5922
5923     if (stream->alignment > 1)
5924       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5925     gst_pad_push (stream->pad, buffer);
5926
5927     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5928   }
5929
5930   /* we're going to modify the metadata */
5931   buf = gst_buffer_make_writable (buf);
5932
5933   if (G_UNLIKELY (stream->need_process))
5934     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5935
5936   if (!buf) {
5937     goto exit;
5938   }
5939
5940   GST_BUFFER_DTS (buf) = dts;
5941   GST_BUFFER_PTS (buf) = pts;
5942   GST_BUFFER_DURATION (buf) = duration;
5943   GST_BUFFER_OFFSET (buf) = -1;
5944   GST_BUFFER_OFFSET_END (buf) = -1;
5945
5946   if (!keyframe) {
5947     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5948     stream->on_keyframe = FALSE;
5949   } else {
5950     stream->on_keyframe = TRUE;
5951   }
5952
5953   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5954     gst_buffer_append_memory (buf,
5955         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5956
5957   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5958     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5959   }
5960 #if 0
5961   if (G_UNLIKELY (qtdemux->element_index)) {
5962     GstClockTime stream_time;
5963
5964     stream_time =
5965         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5966         timestamp);
5967     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5968       GST_LOG_OBJECT (qtdemux,
5969           "adding association %" GST_TIME_FORMAT "-> %"
5970           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5971       gst_index_add_association (qtdemux->element_index,
5972           qtdemux->index_id,
5973           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5974           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5975           GST_FORMAT_BYTES, byte_position, NULL);
5976     }
5977   }
5978 #endif
5979
5980   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
5981
5982 exit:
5983   return ret;
5984 }
5985
5986 static const QtDemuxRandomAccessEntry *
5987 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5988     GstClockTime pos, gboolean after)
5989 {
5990   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5991   guint n_entries = stream->n_ra_entries;
5992   guint i;
5993
5994   /* we assume the table is sorted */
5995   for (i = 0; i < n_entries; ++i) {
5996     if (entries[i].ts > pos)
5997       break;
5998   }
5999
6000   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6001    * probably okay to assume that the index lists the very first fragment */
6002   if (i == 0)
6003     return &entries[0];
6004
6005   if (after)
6006     return &entries[i];
6007   else
6008     return &entries[i - 1];
6009 }
6010
6011 static gboolean
6012 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6013 {
6014   const QtDemuxRandomAccessEntry *best_entry = NULL;
6015   gint i;
6016
6017   GST_OBJECT_LOCK (qtdemux);
6018
6019   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6020
6021   /* first see if we can determine where to go to using mfra,
6022    * before we start clearing things */
6023   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6024     const QtDemuxRandomAccessEntry *entry;
6025     QtDemuxStream *stream;
6026     gboolean is_audio_or_video;
6027
6028     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6029
6030     if (stream->ra_entries == NULL)
6031       continue;
6032
6033     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6034       is_audio_or_video = TRUE;
6035     else
6036       is_audio_or_video = FALSE;
6037
6038     entry =
6039         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6040         stream->time_position, !is_audio_or_video);
6041
6042     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6043         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6044
6045     stream->pending_seek = entry;
6046
6047     /* decide position to jump to just based on audio/video tracks, not subs */
6048     if (!is_audio_or_video)
6049       continue;
6050
6051     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6052       best_entry = entry;
6053   }
6054
6055   /* no luck, will handle seek otherwise */
6056   if (best_entry == NULL) {
6057     GST_OBJECT_UNLOCK (qtdemux);
6058     return FALSE;
6059   }
6060
6061   /* ok, now we can prepare for processing as of located moof */
6062   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6063     QtDemuxStream *stream;
6064
6065     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6066
6067     g_free (stream->samples);
6068     stream->samples = NULL;
6069     stream->n_samples = 0;
6070     stream->stbl_index = -1;    /* no samples have yet been parsed */
6071     stream->sample_index = -1;
6072
6073     if (stream->protection_scheme_info) {
6074       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6075       if (stream->protection_scheme_type == FOURCC_cenc) {
6076         QtDemuxCencSampleSetInfo *info =
6077             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6078         if (info->crypto_info) {
6079           g_ptr_array_free (info->crypto_info, TRUE);
6080           info->crypto_info = NULL;
6081         }
6082       }
6083     }
6084   }
6085
6086   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6087       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6088       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6089       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6090
6091   qtdemux->moof_offset = best_entry->moof_offset;
6092
6093   qtdemux_add_fragmented_samples (qtdemux);
6094
6095   GST_OBJECT_UNLOCK (qtdemux);
6096   return TRUE;
6097 }
6098
6099 static GstFlowReturn
6100 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6101 {
6102   GstFlowReturn ret = GST_FLOW_OK;
6103   GstBuffer *buf = NULL;
6104   QtDemuxStream *stream, *target_stream = NULL;
6105   GstClockTime min_time;
6106   guint64 offset = 0;
6107   GstClockTime dts = GST_CLOCK_TIME_NONE;
6108   GstClockTime pts = GST_CLOCK_TIME_NONE;
6109   GstClockTime duration = 0;
6110   gboolean keyframe = FALSE;
6111   guint sample_size = 0;
6112   guint num_samples = 1;
6113   gboolean empty = 0;
6114   guint size;
6115   gint i;
6116
6117   if (qtdemux->fragmented_seek_pending) {
6118     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6119     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6120       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6121       qtdemux->fragmented_seek_pending = FALSE;
6122     } else {
6123       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6124     }
6125   }
6126
6127   /* Figure out the next stream sample to output, min_time is expressed in
6128    * global time and runs over the edit list segments. */
6129   min_time = G_MAXUINT64;
6130   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6131     GstClockTime position;
6132
6133     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6134     position = stream->time_position;
6135
6136     if (!GST_CLOCK_TIME_IS_VALID (position))
6137       continue;
6138
6139     if (stream->segment_index != -1) {
6140       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6141       position += segment->media_start;
6142     }
6143
6144     /* position of -1 is EOS */
6145     if (position < min_time) {
6146       min_time = position;
6147       target_stream = stream;
6148     }
6149   }
6150   /* all are EOS */
6151   if (G_UNLIKELY (target_stream == NULL)) {
6152     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6153     goto eos;
6154   }
6155
6156   /* check for segment end */
6157   if (G_UNLIKELY (qtdemux->segment.stop != -1
6158           && qtdemux->segment.rate >= 0
6159           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6160     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6161     target_stream->time_position = GST_CLOCK_TIME_NONE;
6162     goto eos_stream;
6163   }
6164
6165   /* gap events for subtitle streams */
6166   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6167     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6168     if (stream->pad) {
6169       GstClockTime gap_threshold;
6170
6171       /* Only send gap events on non-subtitle streams if lagging way behind. */
6172       if (stream->subtype == FOURCC_subp
6173           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)
6174         gap_threshold = 1 * GST_SECOND;
6175       else
6176         gap_threshold = 3 * GST_SECOND;
6177
6178       /* send gap events until the stream catches up */
6179       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6180       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6181           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6182           stream->segment.position + gap_threshold < min_time) {
6183         GstEvent *gap =
6184             gst_event_new_gap (stream->segment.position, gap_threshold);
6185         gst_pad_push_event (stream->pad, gap);
6186         stream->segment.position += gap_threshold;
6187       }
6188     }
6189   }
6190
6191   stream = target_stream;
6192   /* fetch info for the current sample of this stream */
6193   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6194               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6195     goto eos_stream;
6196
6197   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6198   if (stream->new_caps) {
6199     gst_qtdemux_configure_stream (qtdemux, stream);
6200     qtdemux_do_allocation (stream, qtdemux);
6201   }
6202
6203   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6204   if (G_UNLIKELY (qtdemux->segment.
6205           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6206     if (stream->subtype == FOURCC_vide) {
6207       if (!keyframe) {
6208         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6209             stream->track_id);
6210         goto next;
6211       } else if (qtdemux->trickmode_interval > 0) {
6212         GstClockTimeDiff interval;
6213
6214         if (qtdemux->segment.rate > 0)
6215           interval = stream->time_position - stream->last_keyframe_dts;
6216         else
6217           interval = stream->last_keyframe_dts - stream->time_position;
6218
6219         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6220             && interval < qtdemux->trickmode_interval) {
6221           GST_LOG_OBJECT (qtdemux,
6222               "Skipping keyframe within interval on track-id %u",
6223               stream->track_id);
6224           goto next;
6225         } else {
6226           stream->last_keyframe_dts = stream->time_position;
6227         }
6228       }
6229     }
6230   }
6231
6232   GST_DEBUG_OBJECT (qtdemux,
6233       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6234       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6235       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6236       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6237       GST_TIME_ARGS (duration));
6238
6239   if (G_UNLIKELY (empty)) {
6240     /* empty segment, push a gap if there's a second or more
6241      * difference and move to the next one */
6242     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6243       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6244     stream->segment.position = pts + duration;
6245     goto next;
6246   }
6247
6248   /* hmm, empty sample, skip and move to next sample */
6249   if (G_UNLIKELY (sample_size <= 0))
6250     goto next;
6251
6252   /* last pushed sample was out of boundary, goto next sample */
6253   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6254     goto next;
6255
6256   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6257     GST_DEBUG_OBJECT (qtdemux,
6258         "size %d larger than stream max_buffer_size %d, trimming",
6259         sample_size, stream->max_buffer_size);
6260     size =
6261         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6262   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6263       && sample_size < stream->min_buffer_size) {
6264     guint start_sample_index = stream->sample_index;
6265     guint accumulated_size = sample_size;
6266     guint64 expected_next_offset = offset + sample_size;
6267
6268     GST_DEBUG_OBJECT (qtdemux,
6269         "size %d smaller than stream min_buffer_size %d, combining with the next",
6270         sample_size, stream->min_buffer_size);
6271
6272     while (stream->sample_index < stream->to_sample
6273         && stream->sample_index + 1 < stream->n_samples) {
6274       const QtDemuxSample *next_sample;
6275
6276       /* Increment temporarily */
6277       stream->sample_index++;
6278
6279       /* Failed to parse sample so let's go back to the previous one that was
6280        * still successful */
6281       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6282         stream->sample_index--;
6283         break;
6284       }
6285
6286       next_sample = &stream->samples[stream->sample_index];
6287
6288       /* Not contiguous with the previous sample so let's go back to the
6289        * previous one that was still successful */
6290       if (next_sample->offset != expected_next_offset) {
6291         stream->sample_index--;
6292         break;
6293       }
6294
6295       accumulated_size += next_sample->size;
6296       expected_next_offset += next_sample->size;
6297       if (accumulated_size >= stream->min_buffer_size)
6298         break;
6299     }
6300
6301     num_samples = stream->sample_index + 1 - start_sample_index;
6302     stream->sample_index = start_sample_index;
6303     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6304         num_samples, accumulated_size);
6305     size = accumulated_size;
6306   } else {
6307     size = sample_size;
6308   }
6309
6310   if (qtdemux->cenc_aux_info_offset > 0) {
6311     GstMapInfo map;
6312     GstByteReader br;
6313     GstBuffer *aux_info = NULL;
6314
6315     /* pull the data stored before the sample */
6316     ret =
6317         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6318         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6319     if (G_UNLIKELY (ret != GST_FLOW_OK))
6320       goto beach;
6321     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6322     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6323     gst_byte_reader_init (&br, map.data + 8, map.size);
6324     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6325             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6326       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6327       gst_buffer_unmap (aux_info, &map);
6328       gst_buffer_unref (aux_info);
6329       ret = GST_FLOW_ERROR;
6330       goto beach;
6331     }
6332     gst_buffer_unmap (aux_info, &map);
6333     gst_buffer_unref (aux_info);
6334   }
6335
6336   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6337       offset);
6338
6339   if (stream->use_allocator) {
6340     /* if we have a per-stream allocator, use it */
6341     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6342   }
6343
6344   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6345       size, &buf);
6346   if (G_UNLIKELY (ret != GST_FLOW_OK))
6347     goto beach;
6348
6349   /* Update for both splitting and combining of samples */
6350   if (size != sample_size) {
6351     pts += gst_util_uint64_scale_int (GST_SECOND,
6352         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6353         stream->timescale);
6354     dts +=
6355         gst_util_uint64_scale_int (GST_SECOND,
6356         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6357         stream->timescale);
6358     duration =
6359         gst_util_uint64_scale_int (GST_SECOND,
6360         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6361   }
6362
6363   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6364       dts, pts, duration, keyframe, min_time, offset);
6365
6366   if (size < sample_size) {
6367     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6368     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6369
6370     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6371         sample->timestamp +
6372         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6373     if (time_position >= segment->media_start) {
6374       /* inside the segment, update time_position, looks very familiar to
6375        * GStreamer segments, doesn't it? */
6376       stream->time_position = (time_position - segment->media_start) +
6377           segment->time;
6378     } else {
6379       /* not yet in segment, time does not yet increment. This means
6380        * that we are still prerolling keyframes to the decoder so it can
6381        * decode the first sample of the segment. */
6382       stream->time_position = segment->time;
6383     }
6384   } else if (size > sample_size) {
6385     /* Increase to the last sample we already pulled so that advancing
6386      * below brings us to the next sample we need to pull */
6387     stream->sample_index += num_samples - 1;
6388   }
6389
6390   /* combine flows */
6391   GST_OBJECT_LOCK (qtdemux);
6392   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6393   GST_OBJECT_UNLOCK (qtdemux);
6394   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6395    * we have no more data for the pad to push */
6396   if (ret == GST_FLOW_EOS)
6397     ret = GST_FLOW_OK;
6398
6399   stream->offset_in_sample += size;
6400   if (stream->offset_in_sample >= sample_size) {
6401     gst_qtdemux_advance_sample (qtdemux, stream);
6402   }
6403   goto beach;
6404
6405 next:
6406   gst_qtdemux_advance_sample (qtdemux, stream);
6407
6408 beach:
6409   return ret;
6410
6411   /* special cases */
6412 eos:
6413   {
6414     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6415     ret = GST_FLOW_EOS;
6416     goto beach;
6417   }
6418 eos_stream:
6419   {
6420     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6421     /* EOS will be raised if all are EOS */
6422     ret = GST_FLOW_OK;
6423     goto beach;
6424   }
6425 }
6426
6427 static void
6428 gst_qtdemux_loop (GstPad * pad)
6429 {
6430   GstQTDemux *qtdemux;
6431   guint64 cur_offset;
6432   GstFlowReturn ret;
6433
6434   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6435
6436   cur_offset = qtdemux->offset;
6437   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6438       cur_offset, qt_demux_state_string (qtdemux->state));
6439
6440   switch (qtdemux->state) {
6441     case QTDEMUX_STATE_INITIAL:
6442     case QTDEMUX_STATE_HEADER:
6443       ret = gst_qtdemux_loop_state_header (qtdemux);
6444       break;
6445     case QTDEMUX_STATE_MOVIE:
6446       ret = gst_qtdemux_loop_state_movie (qtdemux);
6447       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6448         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6449       }
6450       break;
6451     default:
6452       /* ouch */
6453       goto invalid_state;
6454   }
6455
6456   /* if something went wrong, pause */
6457   if (ret != GST_FLOW_OK)
6458     goto pause;
6459
6460 done:
6461   gst_object_unref (qtdemux);
6462   return;
6463
6464   /* ERRORS */
6465 invalid_state:
6466   {
6467     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6468         (NULL), ("streaming stopped, invalid state"));
6469     gst_pad_pause_task (pad);
6470     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6471     goto done;
6472   }
6473 pause:
6474   {
6475     const gchar *reason = gst_flow_get_name (ret);
6476
6477     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6478
6479     gst_pad_pause_task (pad);
6480
6481     /* fatal errors need special actions */
6482     /* check EOS */
6483     if (ret == GST_FLOW_EOS) {
6484       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6485         /* we have no streams, post an error */
6486         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6487       }
6488       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6489         gint64 stop;
6490
6491         if ((stop = qtdemux->segment.stop) == -1)
6492           stop = qtdemux->segment.duration;
6493
6494         if (qtdemux->segment.rate >= 0) {
6495           GstMessage *message;
6496           GstEvent *event;
6497
6498           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6499           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6500               GST_FORMAT_TIME, stop);
6501           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6502           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6503             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6504             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6505           }
6506           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6507           gst_qtdemux_push_event (qtdemux, event);
6508         } else {
6509           GstMessage *message;
6510           GstEvent *event;
6511
6512           /*  For Reverse Playback */
6513           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6514           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6515               GST_FORMAT_TIME, qtdemux->segment.start);
6516           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6517               qtdemux->segment.start);
6518           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6519             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6520             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6521           }
6522           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6523           gst_qtdemux_push_event (qtdemux, event);
6524         }
6525       } else {
6526         GstEvent *event;
6527
6528         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6529         event = gst_event_new_eos ();
6530         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6531           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6532         gst_qtdemux_push_event (qtdemux, event);
6533       }
6534     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6535       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6536       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6537     }
6538     goto done;
6539   }
6540 }
6541
6542 /*
6543  * has_next_entry
6544  *
6545  * Returns if there are samples to be played.
6546  */
6547 static gboolean
6548 has_next_entry (GstQTDemux * demux)
6549 {
6550   QtDemuxStream *stream;
6551   gint i;
6552
6553   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6554
6555   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6556     stream = QTDEMUX_NTH_STREAM (demux, i);
6557
6558     if (stream->sample_index == -1) {
6559       stream->sample_index = 0;
6560       stream->offset_in_sample = 0;
6561     }
6562
6563     if (stream->sample_index >= stream->n_samples) {
6564       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6565       continue;
6566     }
6567     GST_DEBUG_OBJECT (demux, "Found a sample");
6568     return TRUE;
6569   }
6570
6571   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6572   return FALSE;
6573 }
6574
6575 /*
6576  * next_entry_size
6577  *
6578  * Returns the size of the first entry at the current offset.
6579  * If -1, there are none (which means EOS or empty file).
6580  */
6581 static guint64
6582 next_entry_size (GstQTDemux * demux)
6583 {
6584   QtDemuxStream *stream, *target_stream = NULL;
6585   guint64 smalloffs = (guint64) - 1;
6586   QtDemuxSample *sample;
6587   gint i;
6588
6589   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6590       demux->offset);
6591
6592   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6593     stream = QTDEMUX_NTH_STREAM (demux, i);
6594
6595     if (stream->sample_index == -1) {
6596       stream->sample_index = 0;
6597       stream->offset_in_sample = 0;
6598     }
6599
6600     if (stream->sample_index >= stream->n_samples) {
6601       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6602       continue;
6603     }
6604
6605     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6606       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6607           stream->sample_index);
6608       return -1;
6609     }
6610
6611     sample = &stream->samples[stream->sample_index];
6612
6613     GST_LOG_OBJECT (demux,
6614         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6615         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6616         stream->sample_index, sample->offset, sample->size);
6617
6618     if (((smalloffs == -1)
6619             || (sample->offset < smalloffs)) && (sample->size)) {
6620       smalloffs = sample->offset;
6621       target_stream = stream;
6622     }
6623   }
6624
6625   if (!target_stream)
6626     return -1;
6627
6628   GST_LOG_OBJECT (demux,
6629       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6630       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6631
6632   stream = target_stream;
6633   sample = &stream->samples[stream->sample_index];
6634
6635   if (sample->offset >= demux->offset) {
6636     demux->todrop = sample->offset - demux->offset;
6637     return sample->size + demux->todrop;
6638   }
6639
6640   GST_DEBUG_OBJECT (demux,
6641       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6642   return -1;
6643 }
6644
6645 static void
6646 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6647 {
6648   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6649
6650   gst_element_post_message (GST_ELEMENT_CAST (demux),
6651       gst_message_new_element (GST_OBJECT_CAST (demux),
6652           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6653 }
6654
6655 static gboolean
6656 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6657 {
6658   GstEvent *event;
6659   gboolean res = 0;
6660
6661   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6662
6663   event =
6664       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6665       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6666       GST_SEEK_TYPE_NONE, -1);
6667
6668   /* store seqnum to drop flush events, they don't need to reach downstream */
6669   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6670   res = gst_pad_push_event (demux->sinkpad, event);
6671   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6672
6673   return res;
6674 }
6675
6676 /* check for seekable upstream, above and beyond a mere query */
6677 static void
6678 gst_qtdemux_check_seekability (GstQTDemux * demux)
6679 {
6680   GstQuery *query;
6681   gboolean seekable = FALSE;
6682   gint64 start = -1, stop = -1;
6683
6684   if (demux->upstream_size)
6685     return;
6686
6687   if (demux->upstream_format_is_time)
6688     return;
6689
6690   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6691   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6692     GST_DEBUG_OBJECT (demux, "seeking query failed");
6693     goto done;
6694   }
6695
6696   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6697
6698   /* try harder to query upstream size if we didn't get it the first time */
6699   if (seekable && stop == -1) {
6700     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6701     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6702   }
6703
6704   /* if upstream doesn't know the size, it's likely that it's not seekable in
6705    * practice even if it technically may be seekable */
6706   if (seekable && (start != 0 || stop <= start)) {
6707     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6708     seekable = FALSE;
6709   }
6710
6711 done:
6712   gst_query_unref (query);
6713
6714   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6715       G_GUINT64_FORMAT ")", seekable, start, stop);
6716   demux->upstream_seekable = seekable;
6717   demux->upstream_size = seekable ? stop : -1;
6718 }
6719
6720 static void
6721 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6722 {
6723   g_return_if_fail (bytes <= demux->todrop);
6724
6725   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6726   gst_adapter_flush (demux->adapter, bytes);
6727   demux->neededbytes -= bytes;
6728   demux->offset += bytes;
6729   demux->todrop -= bytes;
6730 }
6731
6732 /* PUSH-MODE only: Send a segment, if not done already. */
6733 static void
6734 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6735 {
6736   if (G_UNLIKELY (demux->need_segment)) {
6737     gint i;
6738
6739     if (!demux->upstream_format_is_time) {
6740       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6741     } else {
6742       GstEvent *segment_event;
6743       segment_event = gst_event_new_segment (&demux->segment);
6744       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6745         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6746       gst_qtdemux_push_event (demux, segment_event);
6747     }
6748
6749     demux->need_segment = FALSE;
6750
6751     /* clear to send tags on all streams */
6752     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6753       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6754       gst_qtdemux_push_tags (demux, stream);
6755       if (CUR_STREAM (stream)->sparse) {
6756         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6757         gst_pad_push_event (stream->pad,
6758             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6759       }
6760     }
6761   }
6762 }
6763
6764 /* Used for push mode only. */
6765 static void
6766 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6767     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6768 {
6769   GstClockTime ts, dur;
6770
6771   ts = pos;
6772   dur =
6773       stream->segments[segment_index].duration - (pos -
6774       stream->segments[segment_index].time);
6775   stream->time_position += dur;
6776
6777   /* Only gaps with a duration of at least one second are propagated.
6778    * Same workaround as in pull mode.
6779    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6780   if (dur >= GST_SECOND) {
6781     GstEvent *gap;
6782     gap = gst_event_new_gap (ts, dur);
6783
6784     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6785         "segment: %" GST_PTR_FORMAT, gap);
6786     gst_pad_push_event (stream->pad, gap);
6787   }
6788 }
6789
6790 static GstFlowReturn
6791 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6792 {
6793   GstQTDemux *demux;
6794
6795   demux = GST_QTDEMUX (parent);
6796
6797   GST_DEBUG_OBJECT (demux,
6798       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6799       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6800       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6801       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6802       gst_buffer_get_size (inbuf), demux->offset);
6803
6804   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6805     gboolean is_gap_input = FALSE;
6806     gint i;
6807
6808     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6809
6810     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6811       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6812     }
6813
6814     /* Check if we can land back on our feet in the case where upstream is
6815      * handling the seeking/pushing of samples with gaps in between (like
6816      * in the case of trick-mode DASH for example) */
6817     if (demux->upstream_format_is_time
6818         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6819       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6820         guint32 res;
6821         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6822         GST_LOG_OBJECT (demux,
6823             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6824             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6825         res =
6826             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6827             stream, GST_BUFFER_OFFSET (inbuf));
6828         if (res != -1) {
6829           QtDemuxSample *sample = &stream->samples[res];
6830           GST_LOG_OBJECT (demux,
6831               "Checking if sample %d from track-id %u is valid (offset:%"
6832               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6833               stream->track_id, sample->offset, sample->size);
6834           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6835             GST_LOG_OBJECT (demux,
6836                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6837                 res);
6838             is_gap_input = TRUE;
6839             /* We can go back to standard playback mode */
6840             demux->state = QTDEMUX_STATE_MOVIE;
6841             /* Remember which sample this stream is at */
6842             stream->sample_index = res;
6843             /* Finally update all push-based values to the expected values */
6844             demux->neededbytes = stream->samples[res].size;
6845             demux->offset = GST_BUFFER_OFFSET (inbuf);
6846             demux->mdatleft =
6847                 demux->mdatsize - demux->offset + demux->mdatoffset;
6848             demux->todrop = 0;
6849           }
6850         }
6851       }
6852       if (!is_gap_input) {
6853         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6854         /* Reset state if it's a real discont */
6855         demux->neededbytes = 16;
6856         demux->state = QTDEMUX_STATE_INITIAL;
6857         demux->offset = GST_BUFFER_OFFSET (inbuf);
6858         gst_adapter_clear (demux->adapter);
6859       }
6860     }
6861     /* Reverse fragmented playback, need to flush all we have before
6862      * consuming a new fragment.
6863      * The samples array have the timestamps calculated by accumulating the
6864      * durations but this won't work for reverse playback of fragments as
6865      * the timestamps of a subsequent fragment should be smaller than the
6866      * previously received one. */
6867     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6868       gst_qtdemux_process_adapter (demux, TRUE);
6869       g_ptr_array_foreach (demux->active_streams,
6870           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6871     }
6872   }
6873
6874   gst_adapter_push (demux->adapter, inbuf);
6875
6876   GST_DEBUG_OBJECT (demux,
6877       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6878       demux->neededbytes, gst_adapter_available (demux->adapter));
6879
6880   return gst_qtdemux_process_adapter (demux, FALSE);
6881 }
6882
6883 static GstFlowReturn
6884 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6885 {
6886   GstFlowReturn ret = GST_FLOW_OK;
6887
6888   /* we never really mean to buffer that much */
6889   if (demux->neededbytes == -1) {
6890     goto eos;
6891   }
6892
6893   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6894       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6895
6896 #ifndef GST_DISABLE_GST_DEBUG
6897     {
6898       guint64 discont_offset, distance_from_discont;
6899
6900       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6901       distance_from_discont =
6902           gst_adapter_distance_from_discont (demux->adapter);
6903
6904       GST_DEBUG_OBJECT (demux,
6905           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6906           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6907           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6908           demux->offset, discont_offset, distance_from_discont);
6909     }
6910 #endif
6911
6912     switch (demux->state) {
6913       case QTDEMUX_STATE_INITIAL:{
6914         const guint8 *data;
6915         guint32 fourcc;
6916         guint64 size;
6917
6918         gst_qtdemux_check_seekability (demux);
6919
6920         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6921
6922         /* get fourcc/length, set neededbytes */
6923         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6924             &size, &fourcc);
6925         gst_adapter_unmap (demux->adapter);
6926         data = NULL;
6927         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6928             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6929         if (size == 0) {
6930           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6931               (_("This file is invalid and cannot be played.")),
6932               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6933                   GST_FOURCC_ARGS (fourcc)));
6934           ret = GST_FLOW_ERROR;
6935           break;
6936         }
6937         if (fourcc == FOURCC_mdat) {
6938           gint next_entry = next_entry_size (demux);
6939           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
6940                   || !demux->fragmented)) {
6941             /* we have the headers, start playback */
6942             demux->state = QTDEMUX_STATE_MOVIE;
6943             demux->neededbytes = next_entry;
6944             demux->mdatleft = size;
6945             demux->mdatsize = demux->mdatleft;
6946           } else {
6947             /* no headers yet, try to get them */
6948             guint bs;
6949             gboolean res;
6950             guint64 old, target;
6951
6952           buffer_data:
6953             old = demux->offset;
6954             target = old + size;
6955
6956             /* try to jump over the atom with a seek */
6957             /* only bother if it seems worth doing so,
6958              * and avoids possible upstream/server problems */
6959             if (demux->upstream_seekable &&
6960                 demux->upstream_size > 4 * (1 << 20)) {
6961               res = qtdemux_seek_offset (demux, target);
6962             } else {
6963               GST_DEBUG_OBJECT (demux, "skipping seek");
6964               res = FALSE;
6965             }
6966
6967             if (res) {
6968               GST_DEBUG_OBJECT (demux, "seek success");
6969               /* remember the offset fo the first mdat so we can seek back to it
6970                * after we have the headers */
6971               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6972                 demux->first_mdat = old;
6973                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6974                     demux->first_mdat);
6975               }
6976               /* seek worked, continue reading */
6977               demux->offset = target;
6978               demux->neededbytes = 16;
6979               demux->state = QTDEMUX_STATE_INITIAL;
6980             } else {
6981               /* seek failed, need to buffer */
6982               demux->offset = old;
6983               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6984               /* there may be multiple mdat (or alike) buffers */
6985               /* sanity check */
6986               if (demux->mdatbuffer)
6987                 bs = gst_buffer_get_size (demux->mdatbuffer);
6988               else
6989                 bs = 0;
6990               if (size + bs > 10 * (1 << 20))
6991                 goto no_moov;
6992               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6993               demux->neededbytes = size;
6994               if (!demux->mdatbuffer)
6995                 demux->mdatoffset = demux->offset;
6996             }
6997           }
6998         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6999           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7000               (_("This file is invalid and cannot be played.")),
7001               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7002                   GST_FOURCC_ARGS (fourcc), size));
7003           ret = GST_FLOW_ERROR;
7004           break;
7005         } else {
7006           /* this means we already started buffering and still no moov header,
7007            * let's continue buffering everything till we get moov */
7008           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7009                   || fourcc == FOURCC_moof))
7010             goto buffer_data;
7011           demux->neededbytes = size;
7012           demux->state = QTDEMUX_STATE_HEADER;
7013         }
7014         break;
7015       }
7016       case QTDEMUX_STATE_HEADER:{
7017         const guint8 *data;
7018         guint32 fourcc;
7019
7020         GST_DEBUG_OBJECT (demux, "In header");
7021
7022         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7023
7024         /* parse the header */
7025         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7026             &fourcc);
7027         if (fourcc == FOURCC_moov) {
7028           /* in usual fragmented setup we could try to scan for more
7029            * and end up at the the moov (after mdat) again */
7030           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7031               (!demux->fragmented
7032                   || demux->last_moov_offset == demux->offset)) {
7033             GST_DEBUG_OBJECT (demux,
7034                 "Skipping moov atom as we have (this) one already");
7035           } else {
7036             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7037
7038             if (demux->got_moov && demux->fragmented) {
7039               GST_DEBUG_OBJECT (demux,
7040                   "Got a second moov, clean up data from old one");
7041               if (demux->moov_node_compressed) {
7042                 g_node_destroy (demux->moov_node_compressed);
7043                 if (demux->moov_node)
7044                   g_free (demux->moov_node->data);
7045               }
7046               demux->moov_node_compressed = NULL;
7047               if (demux->moov_node)
7048                 g_node_destroy (demux->moov_node);
7049               demux->moov_node = NULL;
7050             }
7051
7052             demux->last_moov_offset = demux->offset;
7053
7054             /* Update streams with new moov */
7055             gst_qtdemux_stream_concat (demux,
7056                 demux->old_streams, demux->active_streams);
7057
7058             qtdemux_parse_moov (demux, data, demux->neededbytes);
7059             qtdemux_node_dump (demux, demux->moov_node);
7060             qtdemux_parse_tree (demux);
7061             qtdemux_prepare_streams (demux);
7062             QTDEMUX_EXPOSE_LOCK (demux);
7063             qtdemux_expose_streams (demux);
7064             QTDEMUX_EXPOSE_UNLOCK (demux);
7065
7066             demux->got_moov = TRUE;
7067
7068             gst_qtdemux_check_send_pending_segment (demux);
7069
7070             if (demux->moov_node_compressed) {
7071               g_node_destroy (demux->moov_node_compressed);
7072               g_free (demux->moov_node->data);
7073             }
7074             demux->moov_node_compressed = NULL;
7075             g_node_destroy (demux->moov_node);
7076             demux->moov_node = NULL;
7077             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7078           }
7079         } else if (fourcc == FOURCC_moof) {
7080           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7081             guint64 dist = 0;
7082             GstClockTime prev_pts;
7083             guint64 prev_offset;
7084             guint64 adapter_discont_offset, adapter_discont_dist;
7085
7086             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7087
7088             /*
7089              * The timestamp of the moof buffer is relevant as some scenarios
7090              * won't have the initial timestamp in the atoms. Whenever a new
7091              * buffer has started, we get that buffer's PTS and use it as a base
7092              * timestamp for the trun entries.
7093              *
7094              * To keep track of the current buffer timestamp and starting point
7095              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7096              * from the beginning of the buffer, with the distance and demux->offset
7097              * we know if it is still the same buffer or not.
7098              */
7099             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7100             prev_offset = demux->offset - dist;
7101             if (demux->fragment_start_offset == -1
7102                 || prev_offset > demux->fragment_start_offset) {
7103               demux->fragment_start_offset = prev_offset;
7104               demux->fragment_start = prev_pts;
7105               GST_DEBUG_OBJECT (demux,
7106                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7107                   GST_TIME_FORMAT, demux->fragment_start_offset,
7108                   GST_TIME_ARGS (demux->fragment_start));
7109             }
7110
7111             /* We can't use prev_offset() here because this would require
7112              * upstream to set consistent and correct offsets on all buffers
7113              * since the discont. Nothing ever did that in the past and we
7114              * would break backwards compatibility here then.
7115              * Instead take the offset we had at the last discont and count
7116              * the bytes from there. This works with old code as there would
7117              * be no discont between moov and moof, and also works with
7118              * adaptivedemux which correctly sets offset and will set the
7119              * DISCONT flag accordingly when needed.
7120              *
7121              * We also only do this for upstream TIME segments as otherwise
7122              * there are potential backwards compatibility problems with
7123              * seeking in PUSH mode and upstream providing inconsistent
7124              * timestamps. */
7125             adapter_discont_offset =
7126                 gst_adapter_offset_at_discont (demux->adapter);
7127             adapter_discont_dist =
7128                 gst_adapter_distance_from_discont (demux->adapter);
7129
7130             GST_DEBUG_OBJECT (demux,
7131                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7132                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7133                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7134
7135             if (demux->upstream_format_is_time) {
7136               demux->moof_offset = adapter_discont_offset;
7137               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7138                 demux->moof_offset += adapter_discont_dist;
7139               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7140                 demux->moof_offset = demux->offset;
7141             } else {
7142               demux->moof_offset = demux->offset;
7143             }
7144
7145             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7146                     demux->moof_offset, NULL)) {
7147               gst_adapter_unmap (demux->adapter);
7148               ret = GST_FLOW_ERROR;
7149               goto done;
7150             }
7151
7152             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7153             if (demux->mss_mode && !demux->exposed) {
7154               QTDEMUX_EXPOSE_LOCK (demux);
7155               qtdemux_expose_streams (demux);
7156               QTDEMUX_EXPOSE_UNLOCK (demux);
7157             }
7158
7159             gst_qtdemux_check_send_pending_segment (demux);
7160           } else {
7161             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7162           }
7163         } else if (fourcc == FOURCC_ftyp) {
7164           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7165           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7166         } else if (fourcc == FOURCC_uuid) {
7167           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7168           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7169         } else if (fourcc == FOURCC_sidx) {
7170           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7171           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7172         } else {
7173           switch (fourcc) {
7174             case FOURCC_styp:
7175               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7176                * FALLTHROUGH */
7177             case FOURCC_skip:
7178             case FOURCC_free:
7179               /* [free] and [skip] are padding atoms */
7180               GST_DEBUG_OBJECT (demux,
7181                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7182                   GST_FOURCC_ARGS (fourcc));
7183               break;
7184             default:
7185               GST_WARNING_OBJECT (demux,
7186                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7187                   GST_FOURCC_ARGS (fourcc));
7188               /* Let's jump that one and go back to initial state */
7189               break;
7190           }
7191         }
7192         gst_adapter_unmap (demux->adapter);
7193         data = NULL;
7194
7195         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7196           gsize remaining_data_size = 0;
7197
7198           /* the mdat was before the header */
7199           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7200               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7201           /* restore our adapter/offset view of things with upstream;
7202            * put preceding buffered data ahead of current moov data.
7203            * This should also handle evil mdat, moov, mdat cases and alike */
7204           gst_adapter_flush (demux->adapter, demux->neededbytes);
7205
7206           /* Store any remaining data after the mdat for later usage */
7207           remaining_data_size = gst_adapter_available (demux->adapter);
7208           if (remaining_data_size > 0) {
7209             g_assert (demux->restoredata_buffer == NULL);
7210             demux->restoredata_buffer =
7211                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7212             demux->restoredata_offset = demux->offset + demux->neededbytes;
7213             GST_DEBUG_OBJECT (demux,
7214                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7215                 G_GUINT64_FORMAT, remaining_data_size,
7216                 demux->restoredata_offset);
7217           }
7218
7219           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7220           demux->mdatbuffer = NULL;
7221           demux->offset = demux->mdatoffset;
7222           demux->neededbytes = next_entry_size (demux);
7223           demux->state = QTDEMUX_STATE_MOVIE;
7224           demux->mdatleft = gst_adapter_available (demux->adapter);
7225           demux->mdatsize = demux->mdatleft;
7226         } else {
7227           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7228           gst_adapter_flush (demux->adapter, demux->neededbytes);
7229
7230           /* only go back to the mdat if there are samples to play */
7231           if (demux->got_moov && demux->first_mdat != -1
7232               && has_next_entry (demux)) {
7233             gboolean res;
7234
7235             /* we need to seek back */
7236             res = qtdemux_seek_offset (demux, demux->first_mdat);
7237             if (res) {
7238               demux->offset = demux->first_mdat;
7239             } else {
7240               GST_DEBUG_OBJECT (demux, "Seek back failed");
7241             }
7242           } else {
7243             demux->offset += demux->neededbytes;
7244           }
7245           demux->neededbytes = 16;
7246           demux->state = QTDEMUX_STATE_INITIAL;
7247         }
7248
7249         break;
7250       }
7251       case QTDEMUX_STATE_BUFFER_MDAT:{
7252         GstBuffer *buf;
7253         guint8 fourcc[4];
7254
7255         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7256             demux->offset);
7257         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7258         gst_buffer_extract (buf, 0, fourcc, 4);
7259         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7260             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7261         if (demux->mdatbuffer)
7262           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7263         else
7264           demux->mdatbuffer = buf;
7265         demux->offset += demux->neededbytes;
7266         demux->neededbytes = 16;
7267         demux->state = QTDEMUX_STATE_INITIAL;
7268         gst_qtdemux_post_progress (demux, 1, 1);
7269
7270         break;
7271       }
7272       case QTDEMUX_STATE_MOVIE:{
7273         QtDemuxStream *stream = NULL;
7274         QtDemuxSample *sample;
7275         GstClockTime dts, pts, duration;
7276         gboolean keyframe;
7277         gint i;
7278
7279         GST_DEBUG_OBJECT (demux,
7280             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7281
7282         if (demux->fragmented) {
7283           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7284               demux->mdatleft);
7285           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7286             /* if needed data starts within this atom,
7287              * then it should not exceed this atom */
7288             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7289               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7290                   (_("This file is invalid and cannot be played.")),
7291                   ("sample data crosses atom boundary"));
7292               ret = GST_FLOW_ERROR;
7293               break;
7294             }
7295             demux->mdatleft -= demux->neededbytes;
7296           } else {
7297             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7298             /* so we are dropping more than left in this atom */
7299             gst_qtdemux_drop_data (demux, demux->mdatleft);
7300             demux->mdatleft = 0;
7301
7302             /* need to resume atom parsing so we do not miss any other pieces */
7303             demux->state = QTDEMUX_STATE_INITIAL;
7304             demux->neededbytes = 16;
7305
7306             /* check if there was any stored post mdat data from previous buffers */
7307             if (demux->restoredata_buffer) {
7308               g_assert (gst_adapter_available (demux->adapter) == 0);
7309
7310               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7311               demux->restoredata_buffer = NULL;
7312               demux->offset = demux->restoredata_offset;
7313             }
7314
7315             break;
7316           }
7317         }
7318
7319         if (demux->todrop) {
7320           if (demux->cenc_aux_info_offset > 0) {
7321             GstByteReader br;
7322             const guint8 *data;
7323
7324             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7325             data = gst_adapter_map (demux->adapter, demux->todrop);
7326             gst_byte_reader_init (&br, data + 8, demux->todrop);
7327             if (!qtdemux_parse_cenc_aux_info (demux,
7328                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7329                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7330               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7331               ret = GST_FLOW_ERROR;
7332               gst_adapter_unmap (demux->adapter);
7333               g_free (demux->cenc_aux_info_sizes);
7334               demux->cenc_aux_info_sizes = NULL;
7335               goto done;
7336             }
7337             demux->cenc_aux_info_offset = 0;
7338             g_free (demux->cenc_aux_info_sizes);
7339             demux->cenc_aux_info_sizes = NULL;
7340             gst_adapter_unmap (demux->adapter);
7341           }
7342           gst_qtdemux_drop_data (demux, demux->todrop);
7343         }
7344
7345         /* first buffer? */
7346         /* initial newsegment sent here after having added pads,
7347          * possible others in sink_event */
7348         gst_qtdemux_check_send_pending_segment (demux);
7349
7350         /* Figure out which stream this packet belongs to */
7351         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7352           stream = QTDEMUX_NTH_STREAM (demux, i);
7353           if (stream->sample_index >= stream->n_samples) {
7354             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7355             stream = NULL;
7356             continue;
7357           }
7358           GST_LOG_OBJECT (demux,
7359               "Checking track-id %u (sample_index:%d / offset:%"
7360               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7361               stream->sample_index,
7362               stream->samples[stream->sample_index].offset,
7363               stream->samples[stream->sample_index].size);
7364
7365           if (stream->samples[stream->sample_index].offset == demux->offset)
7366             break;
7367         }
7368
7369         if (G_UNLIKELY (stream == NULL))
7370           goto unknown_stream;
7371
7372         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7373
7374         if (stream->new_caps) {
7375           gst_qtdemux_configure_stream (demux, stream);
7376         }
7377
7378         /* Put data in a buffer, set timestamps, caps, ... */
7379         sample = &stream->samples[stream->sample_index];
7380
7381         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7382           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7383               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7384
7385           dts = QTSAMPLE_DTS (stream, sample);
7386           pts = QTSAMPLE_PTS (stream, sample);
7387           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7388           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7389
7390           /* check for segment end */
7391           if (G_UNLIKELY (demux->segment.stop != -1
7392                   && demux->segment.stop <= pts && stream->on_keyframe)
7393               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7394             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7395             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7396
7397             /* skip this data, stream is EOS */
7398             gst_adapter_flush (demux->adapter, demux->neededbytes);
7399             demux->offset += demux->neededbytes;
7400
7401             /* check if all streams are eos */
7402             ret = GST_FLOW_EOS;
7403             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7404               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7405                 ret = GST_FLOW_OK;
7406                 break;
7407               }
7408             }
7409           } else {
7410             GstBuffer *outbuf;
7411
7412             outbuf =
7413                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7414
7415             /* FIXME: should either be an assert or a plain check */
7416             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7417
7418             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7419                 dts, pts, duration, keyframe, dts, demux->offset);
7420           }
7421
7422           /* combine flows */
7423           GST_OBJECT_LOCK (demux);
7424           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7425           GST_OBJECT_UNLOCK (demux);
7426         } else {
7427           /* skip this data, stream is EOS */
7428           gst_adapter_flush (demux->adapter, demux->neededbytes);
7429         }
7430
7431         stream->sample_index++;
7432         stream->offset_in_sample = 0;
7433
7434         /* update current offset and figure out size of next buffer */
7435         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7436             demux->offset, demux->neededbytes);
7437         demux->offset += demux->neededbytes;
7438         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7439             demux->offset);
7440
7441
7442         if (ret == GST_FLOW_EOS) {
7443           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7444           demux->neededbytes = -1;
7445           goto eos;
7446         }
7447
7448         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7449           if (demux->fragmented) {
7450             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7451             /* there may be more to follow, only finish this atom */
7452             demux->todrop = demux->mdatleft;
7453             demux->neededbytes = demux->todrop;
7454             break;
7455           }
7456           goto eos;
7457         }
7458         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7459           goto non_ok_unlinked_flow;
7460         }
7461         break;
7462       }
7463       default:
7464         goto invalid_state;
7465     }
7466   }
7467
7468   /* when buffering movie data, at least show user something is happening */
7469   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7470       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7471     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7472         demux->neededbytes);
7473   }
7474 done:
7475
7476   return ret;
7477
7478   /* ERRORS */
7479 non_ok_unlinked_flow:
7480   {
7481     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7482         gst_flow_get_name (ret));
7483     return ret;
7484   }
7485 unknown_stream:
7486   {
7487     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7488     ret = GST_FLOW_ERROR;
7489     goto done;
7490   }
7491 eos:
7492   {
7493     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7494     ret = GST_FLOW_EOS;
7495     goto done;
7496   }
7497 invalid_state:
7498   {
7499     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7500         (NULL), ("qtdemuxer invalid state %d", demux->state));
7501     ret = GST_FLOW_ERROR;
7502     goto done;
7503   }
7504 no_moov:
7505   {
7506     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7507         (NULL), ("no 'moov' atom within the first 10 MB"));
7508     ret = GST_FLOW_ERROR;
7509     goto done;
7510   }
7511 }
7512
7513 static gboolean
7514 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7515 {
7516   GstQuery *query;
7517   gboolean pull_mode;
7518
7519   query = gst_query_new_scheduling ();
7520
7521   if (!gst_pad_peer_query (sinkpad, query)) {
7522     gst_query_unref (query);
7523     goto activate_push;
7524   }
7525
7526   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7527       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7528   gst_query_unref (query);
7529
7530   if (!pull_mode)
7531     goto activate_push;
7532
7533   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7534   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7535
7536 activate_push:
7537   {
7538     GST_DEBUG_OBJECT (sinkpad, "activating push");
7539     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7540   }
7541 }
7542
7543 static gboolean
7544 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7545     GstPadMode mode, gboolean active)
7546 {
7547   gboolean res;
7548   GstQTDemux *demux = GST_QTDEMUX (parent);
7549
7550   switch (mode) {
7551     case GST_PAD_MODE_PUSH:
7552       demux->pullbased = FALSE;
7553       res = TRUE;
7554       break;
7555     case GST_PAD_MODE_PULL:
7556       if (active) {
7557         demux->pullbased = TRUE;
7558         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7559             sinkpad, NULL);
7560       } else {
7561         res = gst_pad_stop_task (sinkpad);
7562       }
7563       break;
7564     default:
7565       res = FALSE;
7566       break;
7567   }
7568   return res;
7569 }
7570
7571 #ifdef HAVE_ZLIB
7572 static void *
7573 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7574 {
7575   guint8 *buffer;
7576   z_stream z;
7577   int ret;
7578
7579   memset (&z, 0, sizeof (z));
7580   z.zalloc = NULL;
7581   z.zfree = NULL;
7582   z.opaque = NULL;
7583
7584   if ((ret = inflateInit (&z)) != Z_OK) {
7585     GST_ERROR ("inflateInit() returned %d", ret);
7586     return NULL;
7587   }
7588
7589   z.next_in = z_buffer;
7590   z.avail_in = z_length;
7591
7592   buffer = (guint8 *) g_malloc (*length);
7593   z.avail_out = *length;
7594   z.next_out = (Bytef *) buffer;
7595   do {
7596     ret = inflate (&z, Z_NO_FLUSH);
7597     if (ret == Z_STREAM_END) {
7598       break;
7599     } else if (ret != Z_OK) {
7600       GST_WARNING ("inflate() returned %d", ret);
7601       break;
7602     }
7603
7604     *length += 4096;
7605     buffer = (guint8 *) g_realloc (buffer, *length);
7606     z.next_out = (Bytef *) (buffer + z.total_out);
7607     z.avail_out += 4096;
7608   } while (z.avail_in > 0);
7609
7610   if (ret != Z_STREAM_END) {
7611     g_free (buffer);
7612     buffer = NULL;
7613     *length = 0;
7614   } else {
7615     *length = z.total_out;
7616   }
7617
7618   inflateEnd (&z);
7619
7620   return buffer;
7621 }
7622 #endif /* HAVE_ZLIB */
7623
7624 static gboolean
7625 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7626 {
7627   GNode *cmov;
7628
7629   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7630
7631   /* counts as header data */
7632   qtdemux->header_size += length;
7633
7634   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7635   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7636
7637   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7638   if (cmov) {
7639     guint32 method;
7640     GNode *dcom;
7641     GNode *cmvd;
7642     guint32 dcom_len;
7643
7644     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7645     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7646     if (dcom == NULL || cmvd == NULL)
7647       goto invalid_compression;
7648
7649     dcom_len = QT_UINT32 (dcom->data);
7650     if (dcom_len < 12)
7651       goto invalid_compression;
7652
7653     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7654     switch (method) {
7655 #ifdef HAVE_ZLIB
7656       case FOURCC_zlib:{
7657         guint uncompressed_length;
7658         guint compressed_length;
7659         guint8 *buf;
7660         guint32 cmvd_len;
7661
7662         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7663         if (cmvd_len < 12)
7664           goto invalid_compression;
7665
7666         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7667         compressed_length = cmvd_len - 12;
7668         GST_LOG ("length = %u", uncompressed_length);
7669
7670         buf =
7671             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7672             compressed_length, &uncompressed_length);
7673
7674         if (buf) {
7675           qtdemux->moov_node_compressed = qtdemux->moov_node;
7676           qtdemux->moov_node = g_node_new (buf);
7677
7678           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7679               uncompressed_length);
7680         }
7681         break;
7682       }
7683 #endif /* HAVE_ZLIB */
7684       default:
7685         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7686             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7687         break;
7688     }
7689   }
7690   return TRUE;
7691
7692   /* ERRORS */
7693 invalid_compression:
7694   {
7695     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7696     return FALSE;
7697   }
7698 }
7699
7700 static gboolean
7701 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7702     const guint8 * end)
7703 {
7704   while (G_UNLIKELY (buf < end)) {
7705     GNode *child;
7706     guint32 len;
7707
7708     if (G_UNLIKELY (buf + 4 > end)) {
7709       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7710       break;
7711     }
7712     len = QT_UINT32 (buf);
7713     if (G_UNLIKELY (len == 0)) {
7714       GST_LOG_OBJECT (qtdemux, "empty container");
7715       break;
7716     }
7717     if (G_UNLIKELY (len < 8)) {
7718       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7719       break;
7720     }
7721     if (G_UNLIKELY (len > (end - buf))) {
7722       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7723           (gint) (end - buf));
7724       break;
7725     }
7726
7727     child = g_node_new ((guint8 *) buf);
7728     g_node_append (node, child);
7729     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7730     qtdemux_parse_node (qtdemux, child, buf, len);
7731
7732     buf += len;
7733   }
7734   return TRUE;
7735 }
7736
7737 static gboolean
7738 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7739     GNode * xdxt)
7740 {
7741   int len = QT_UINT32 (xdxt->data);
7742   guint8 *buf = xdxt->data;
7743   guint8 *end = buf + len;
7744   GstBuffer *buffer;
7745
7746   /* skip size and type */
7747   buf += 8;
7748   end -= 8;
7749
7750   while (buf < end) {
7751     gint size;
7752     guint32 type;
7753
7754     size = QT_UINT32 (buf);
7755     type = QT_FOURCC (buf + 4);
7756
7757     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7758
7759     if (buf + size > end || size <= 0)
7760       break;
7761
7762     buf += 8;
7763     size -= 8;
7764
7765     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7766         GST_FOURCC_ARGS (type));
7767
7768     switch (type) {
7769       case FOURCC_tCtH:
7770         buffer = gst_buffer_new_and_alloc (size);
7771         gst_buffer_fill (buffer, 0, buf, size);
7772         stream->buffers = g_slist_append (stream->buffers, buffer);
7773         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7774         break;
7775       case FOURCC_tCt_:
7776         buffer = gst_buffer_new_and_alloc (size);
7777         gst_buffer_fill (buffer, 0, buf, size);
7778         stream->buffers = g_slist_append (stream->buffers, buffer);
7779         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7780         break;
7781       case FOURCC_tCtC:
7782         buffer = gst_buffer_new_and_alloc (size);
7783         gst_buffer_fill (buffer, 0, buf, size);
7784         stream->buffers = g_slist_append (stream->buffers, buffer);
7785         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7786         break;
7787       default:
7788         GST_WARNING_OBJECT (qtdemux,
7789             "unknown theora cookie %" GST_FOURCC_FORMAT,
7790             GST_FOURCC_ARGS (type));
7791         break;
7792     }
7793     buf += size;
7794   }
7795   return TRUE;
7796 }
7797
7798 static gboolean
7799 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7800     guint length)
7801 {
7802   guint32 fourcc = 0;
7803   guint32 node_length = 0;
7804   const QtNodeType *type;
7805   const guint8 *end;
7806
7807   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7808
7809   if (G_UNLIKELY (length < 8))
7810     goto not_enough_data;
7811
7812   node_length = QT_UINT32 (buffer);
7813   fourcc = QT_FOURCC (buffer + 4);
7814
7815   /* ignore empty nodes */
7816   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7817     return TRUE;
7818
7819   type = qtdemux_type_get (fourcc);
7820
7821   end = buffer + length;
7822
7823   GST_LOG_OBJECT (qtdemux,
7824       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7825       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7826
7827   if (node_length > length)
7828     goto broken_atom_size;
7829
7830   if (type->flags & QT_FLAG_CONTAINER) {
7831     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7832   } else {
7833     switch (fourcc) {
7834       case FOURCC_stsd:
7835       {
7836         if (node_length < 20) {
7837           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7838           break;
7839         }
7840         GST_DEBUG_OBJECT (qtdemux,
7841             "parsing stsd (sample table, sample description) atom");
7842         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7843         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7844         break;
7845       }
7846       case FOURCC_mp4a:
7847       case FOURCC_alac:
7848       case FOURCC_fLaC:
7849       {
7850         guint32 version;
7851         guint32 offset;
7852         guint min_size;
7853
7854         /* also read alac (or whatever) in stead of mp4a in the following,
7855          * since a similar layout is used in other cases as well */
7856         if (fourcc == FOURCC_mp4a)
7857           min_size = 20;
7858         else if (fourcc == FOURCC_fLaC)
7859           min_size = 86;
7860         else
7861           min_size = 40;
7862
7863         /* There are two things we might encounter here: a true mp4a atom, and
7864            an mp4a entry in an stsd atom. The latter is what we're interested
7865            in, and it looks like an atom, but isn't really one. The true mp4a
7866            atom is short, so we detect it based on length here. */
7867         if (length < min_size) {
7868           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7869               GST_FOURCC_ARGS (fourcc));
7870           break;
7871         }
7872
7873         /* 'version' here is the sound sample description version. Types 0 and
7874            1 are documented in the QTFF reference, but type 2 is not: it's
7875            described in Apple header files instead (struct SoundDescriptionV2
7876            in Movies.h) */
7877         version = QT_UINT16 (buffer + 16);
7878
7879         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7880             GST_FOURCC_ARGS (fourcc), version);
7881
7882         /* parse any esds descriptors */
7883         switch (version) {
7884           case 0:
7885             offset = 0x24;
7886             break;
7887           case 1:
7888             offset = 0x34;
7889             break;
7890           case 2:
7891             offset = 0x48;
7892             break;
7893           default:
7894             GST_WARNING_OBJECT (qtdemux,
7895                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7896                 GST_FOURCC_ARGS (fourcc), version);
7897             offset = 0;
7898             break;
7899         }
7900         if (offset)
7901           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7902         break;
7903       }
7904       case FOURCC_mp4v:
7905       case FOURCC_MP4V:
7906       case FOURCC_fmp4:
7907       case FOURCC_FMP4:
7908       case FOURCC_apcs:
7909       case FOURCC_apch:
7910       case FOURCC_apcn:
7911       case FOURCC_apco:
7912       case FOURCC_ap4h:
7913       case FOURCC_xvid:
7914       case FOURCC_XVID:
7915       case FOURCC_H264:
7916       case FOURCC_avc1:
7917       case FOURCC_avc3:
7918       case FOURCC_H265:
7919       case FOURCC_hvc1:
7920       case FOURCC_hev1:
7921       case FOURCC_mjp2:
7922       case FOURCC_encv:
7923       {
7924         guint32 version;
7925         guint32 str_len;
7926
7927         /* codec_data is contained inside these atoms, which all have
7928          * the same format. */
7929         /* video sample description size is 86 bytes without extension.
7930          * node_length have to be bigger than 86 bytes because video sample
7931          * description can include extensions such as esds, fiel, glbl, etc. */
7932         if (node_length < 86) {
7933           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7934               " sample description length too short (%u < 86)",
7935               GST_FOURCC_ARGS (fourcc), node_length);
7936           break;
7937         }
7938
7939         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7940             GST_FOURCC_ARGS (fourcc));
7941
7942         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7943          *              its data format.
7944          * revision level (2 bytes) : must be set to 0. */
7945         version = QT_UINT32 (buffer + 16);
7946         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7947
7948         /* compressor name : PASCAL string and informative purposes
7949          * first byte : the number of bytes to be displayed.
7950          *              it has to be less than 32 because it is reserved
7951          *              space of 32 bytes total including itself. */
7952         str_len = QT_UINT8 (buffer + 50);
7953         if (str_len < 32)
7954           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7955               (char *) buffer + 51);
7956         else
7957           GST_WARNING_OBJECT (qtdemux,
7958               "compressorname length too big (%u > 31)", str_len);
7959
7960         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7961             end - buffer);
7962         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7963         break;
7964       }
7965       case FOURCC_meta:
7966       {
7967         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7968
7969         /* You are reading this correctly. QTFF specifies that the
7970          * metadata atom is a short atom, whereas ISO BMFF specifies
7971          * it's a full atom. But since so many people are doing things
7972          * differently, we actually peek into the atom to see which
7973          * variant it is */
7974         if (length < 16) {
7975           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7976               GST_FOURCC_ARGS (fourcc));
7977           break;
7978         }
7979         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7980           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7981            * starts with a 'hdlr' atom */
7982           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7983         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7984           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7985            * with version/flags both set to zero */
7986           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7987         } else
7988           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7989         break;
7990       }
7991       case FOURCC_mp4s:
7992       {
7993         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7994         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7995         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7996         break;
7997       }
7998       case FOURCC_XiTh:
7999       {
8000         guint32 version;
8001         guint32 offset;
8002
8003         if (length < 16) {
8004           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8005               GST_FOURCC_ARGS (fourcc));
8006           break;
8007         }
8008
8009         version = QT_UINT32 (buffer + 12);
8010         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8011
8012         switch (version) {
8013           case 0x00000001:
8014             offset = 0x62;
8015             break;
8016           default:
8017             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8018             offset = 0;
8019             break;
8020         }
8021         if (offset) {
8022           if (length < offset) {
8023             GST_WARNING_OBJECT (qtdemux,
8024                 "skipping too small %" GST_FOURCC_FORMAT " box",
8025                 GST_FOURCC_ARGS (fourcc));
8026             break;
8027           }
8028           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8029         }
8030         break;
8031       }
8032       case FOURCC_in24:
8033       {
8034         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8035         break;
8036       }
8037       case FOURCC_uuid:
8038       {
8039         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8040         break;
8041       }
8042       case FOURCC_enca:
8043       {
8044         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8045         break;
8046       }
8047       default:
8048         if (!strcmp (type->name, "unknown"))
8049           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8050         break;
8051     }
8052   }
8053   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8054       GST_FOURCC_ARGS (fourcc));
8055   return TRUE;
8056
8057 /* ERRORS */
8058 not_enough_data:
8059   {
8060     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8061         (_("This file is corrupt and cannot be played.")),
8062         ("Not enough data for an atom header, got only %u bytes", length));
8063     return FALSE;
8064   }
8065 broken_atom_size:
8066   {
8067     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8068         (_("This file is corrupt and cannot be played.")),
8069         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8070             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8071             length));
8072     return FALSE;
8073   }
8074 }
8075
8076 static void
8077 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8078 {
8079 /* FIXME: This can only reliably work if demuxers have a
8080  * separate streaming thread per srcpad. This should be
8081  * done in a demuxer base class, which integrates parts
8082  * of multiqueue
8083  *
8084  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8085  */
8086 #if 0
8087   GstQuery *query;
8088
8089   query = gst_query_new_allocation (stream->caps, FALSE);
8090
8091   if (!gst_pad_peer_query (stream->pad, query)) {
8092     /* not a problem, just debug a little */
8093     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8094   }
8095
8096   if (stream->allocator)
8097     gst_object_unref (stream->allocator);
8098
8099   if (gst_query_get_n_allocation_params (query) > 0) {
8100     /* try the allocator */
8101     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8102         &stream->params);
8103     stream->use_allocator = TRUE;
8104   } else {
8105     stream->allocator = NULL;
8106     gst_allocation_params_init (&stream->params);
8107     stream->use_allocator = FALSE;
8108   }
8109   gst_query_unref (query);
8110 #endif
8111 }
8112
8113 static gboolean
8114 pad_query (const GValue * item, GValue * value, gpointer user_data)
8115 {
8116   GstPad *pad = g_value_get_object (item);
8117   GstQuery *query = user_data;
8118   gboolean res;
8119
8120   res = gst_pad_peer_query (pad, query);
8121
8122   if (res) {
8123     g_value_set_boolean (value, TRUE);
8124     return FALSE;
8125   }
8126
8127   GST_INFO_OBJECT (pad, "pad peer query failed");
8128   return TRUE;
8129 }
8130
8131 static gboolean
8132 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8133     GstPadDirection direction)
8134 {
8135   GstIterator *it;
8136   GstIteratorFoldFunction func = pad_query;
8137   GValue res = { 0, };
8138
8139   g_value_init (&res, G_TYPE_BOOLEAN);
8140   g_value_set_boolean (&res, FALSE);
8141
8142   /* Ask neighbor */
8143   if (direction == GST_PAD_SRC)
8144     it = gst_element_iterate_src_pads (element);
8145   else
8146     it = gst_element_iterate_sink_pads (element);
8147
8148   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8149     gst_iterator_resync (it);
8150
8151   gst_iterator_free (it);
8152
8153   return g_value_get_boolean (&res);
8154 }
8155
8156 static void
8157 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8158     QtDemuxStream * stream)
8159 {
8160   GstQuery *query;
8161   GstContext *ctxt;
8162   GstElement *element = GST_ELEMENT (qtdemux);
8163   GstStructure *st;
8164   gchar **filtered_sys_ids;
8165   GValue event_list = G_VALUE_INIT;
8166   GList *walk;
8167
8168   /* 1. Check if we already have the context. */
8169   if (qtdemux->preferred_protection_system_id != NULL) {
8170     GST_LOG_OBJECT (element,
8171         "already have the protection context, no need to request it again");
8172     return;
8173   }
8174
8175   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8176   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8177       (const gchar **) qtdemux->protection_system_ids->pdata);
8178
8179   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8180       qtdemux->protection_system_ids->len - 1);
8181   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8182       "decryptors for %u of them, running context request",
8183       qtdemux->protection_system_ids->len,
8184       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8185
8186
8187   if (stream->protection_scheme_event_queue.length) {
8188     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8189         stream->protection_scheme_event_queue.length);
8190     walk = stream->protection_scheme_event_queue.tail;
8191   } else {
8192     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8193         qtdemux->protection_event_queue.length);
8194     walk = qtdemux->protection_event_queue.tail;
8195   }
8196
8197   g_value_init (&event_list, GST_TYPE_LIST);
8198   for (; walk; walk = g_list_previous (walk)) {
8199     GValue *event_value = g_new0 (GValue, 1);
8200     g_value_init (event_value, GST_TYPE_EVENT);
8201     g_value_set_boxed (event_value, walk->data);
8202     gst_value_list_append_and_take_value (&event_list, event_value);
8203   }
8204
8205   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8206    *      check if downstream already has a context of the specific type
8207    *  2b) Query upstream as above.
8208    */
8209   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8210   st = gst_query_writable_structure (query);
8211   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8212       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8213       NULL);
8214   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8215   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8216     gst_query_parse_context (query, &ctxt);
8217     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8218     gst_element_set_context (element, ctxt);
8219   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8220     gst_query_parse_context (query, &ctxt);
8221     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8222     gst_element_set_context (element, ctxt);
8223   } else {
8224     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8225      *    the required context type and afterwards check if a
8226      *    usable context was set now as in 1). The message could
8227      *    be handled by the parent bins of the element and the
8228      *    application.
8229      */
8230     GstMessage *msg;
8231
8232     GST_INFO_OBJECT (element, "posting need context message");
8233     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8234         "drm-preferred-decryption-system-id");
8235     st = (GstStructure *) gst_message_get_structure (msg);
8236     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8237         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8238         NULL);
8239
8240     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8241     gst_element_post_message (element, msg);
8242   }
8243
8244   g_strfreev (filtered_sys_ids);
8245   g_value_unset (&event_list);
8246   gst_query_unref (query);
8247 }
8248
8249 static gboolean
8250 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8251     QtDemuxStream * stream)
8252 {
8253   GstStructure *s;
8254   const gchar *selected_system = NULL;
8255
8256   g_return_val_if_fail (qtdemux != NULL, FALSE);
8257   g_return_val_if_fail (stream != NULL, FALSE);
8258   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8259       FALSE);
8260
8261   if (stream->protection_scheme_type != FOURCC_cenc) {
8262     GST_ERROR_OBJECT (qtdemux,
8263         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8264         GST_FOURCC_ARGS (stream->protection_scheme_type));
8265     return FALSE;
8266   }
8267   if (qtdemux->protection_system_ids == NULL) {
8268     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8269         "cenc protection system information has been found");
8270     return FALSE;
8271   }
8272
8273   gst_qtdemux_request_protection_context (qtdemux, stream);
8274   if (qtdemux->preferred_protection_system_id != NULL) {
8275     const gchar *preferred_system_array[] =
8276         { qtdemux->preferred_protection_system_id, NULL };
8277
8278     selected_system = gst_protection_select_system (preferred_system_array);
8279
8280     if (selected_system) {
8281       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8282           qtdemux->preferred_protection_system_id);
8283     } else {
8284       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8285           "because there is no available decryptor",
8286           qtdemux->preferred_protection_system_id);
8287     }
8288   }
8289
8290   if (!selected_system) {
8291     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8292     selected_system = gst_protection_select_system ((const gchar **)
8293         qtdemux->protection_system_ids->pdata);
8294     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8295         qtdemux->protection_system_ids->len - 1);
8296   }
8297
8298   if (!selected_system) {
8299     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8300         "suitable decryptor element has been found");
8301     return FALSE;
8302   }
8303
8304   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8305       selected_system);
8306
8307   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8308   if (!gst_structure_has_name (s, "application/x-cenc")) {
8309     gst_structure_set (s,
8310         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8311         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8312         NULL);
8313     gst_structure_set_name (s, "application/x-cenc");
8314   }
8315   return TRUE;
8316 }
8317
8318 static gboolean
8319 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8320 {
8321   /* fps is calculated base on the duration of the average framerate since
8322    * qt does not have a fixed framerate. */
8323   gboolean fps_available = TRUE;
8324   guint32 first_duration = 0;
8325
8326   if (stream->n_samples > 0)
8327     first_duration = stream->samples[0].duration;
8328
8329   if ((stream->n_samples == 1 && first_duration == 0)
8330       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8331     /* still frame */
8332     CUR_STREAM (stream)->fps_n = 0;
8333     CUR_STREAM (stream)->fps_d = 1;
8334   } else {
8335     if (stream->duration == 0 || stream->n_samples < 2) {
8336       CUR_STREAM (stream)->fps_n = stream->timescale;
8337       CUR_STREAM (stream)->fps_d = 1;
8338       fps_available = FALSE;
8339     } else {
8340       GstClockTime avg_duration;
8341       guint64 duration;
8342       guint32 n_samples;
8343
8344       /* duration and n_samples can be updated for fragmented format
8345        * so, framerate of fragmented format is calculated using data in a moof */
8346       if (qtdemux->fragmented && stream->n_samples_moof > 0
8347           && stream->duration_moof > 0) {
8348         n_samples = stream->n_samples_moof;
8349         duration = stream->duration_moof;
8350       } else {
8351         n_samples = stream->n_samples;
8352         duration = stream->duration;
8353       }
8354
8355       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8356       /* stream->duration is guint64, timescale, n_samples are guint32 */
8357       avg_duration =
8358           gst_util_uint64_scale_round (duration -
8359           first_duration, GST_SECOND,
8360           (guint64) (stream->timescale) * (n_samples - 1));
8361
8362       GST_LOG_OBJECT (qtdemux,
8363           "Calculating avg sample duration based on stream (or moof) duration %"
8364           G_GUINT64_FORMAT
8365           " minus first sample %u, leaving %d samples gives %"
8366           GST_TIME_FORMAT, duration, first_duration,
8367           n_samples - 1, GST_TIME_ARGS (avg_duration));
8368
8369       fps_available =
8370           gst_video_guess_framerate (avg_duration,
8371           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8372
8373       GST_DEBUG_OBJECT (qtdemux,
8374           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8375           stream->timescale, CUR_STREAM (stream)->fps_n,
8376           CUR_STREAM (stream)->fps_d);
8377     }
8378   }
8379
8380   return fps_available;
8381 }
8382
8383 static gboolean
8384 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8385 {
8386   if (stream->subtype == FOURCC_vide) {
8387     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8388
8389     if (CUR_STREAM (stream)->caps) {
8390       CUR_STREAM (stream)->caps =
8391           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8392
8393       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8394         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8395             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8396             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8397
8398       /* set framerate if calculated framerate is reliable */
8399       if (fps_available) {
8400         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8401             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8402             CUR_STREAM (stream)->fps_d, NULL);
8403       }
8404
8405       /* calculate pixel-aspect-ratio using display width and height */
8406       GST_DEBUG_OBJECT (qtdemux,
8407           "video size %dx%d, target display size %dx%d",
8408           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8409           stream->display_width, stream->display_height);
8410       /* qt file might have pasp atom */
8411       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8412         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8413             CUR_STREAM (stream)->par_h);
8414         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8415             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8416             CUR_STREAM (stream)->par_h, NULL);
8417       } else if (stream->display_width > 0 && stream->display_height > 0
8418           && CUR_STREAM (stream)->width > 0
8419           && CUR_STREAM (stream)->height > 0) {
8420         gint n, d;
8421
8422         /* calculate the pixel aspect ratio using the display and pixel w/h */
8423         n = stream->display_width * CUR_STREAM (stream)->height;
8424         d = stream->display_height * CUR_STREAM (stream)->width;
8425         if (n == d)
8426           n = d = 1;
8427         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8428         CUR_STREAM (stream)->par_w = n;
8429         CUR_STREAM (stream)->par_h = d;
8430         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8431             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8432             CUR_STREAM (stream)->par_h, NULL);
8433       }
8434
8435       if (CUR_STREAM (stream)->interlace_mode > 0) {
8436         if (CUR_STREAM (stream)->interlace_mode == 1) {
8437           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8438               G_TYPE_STRING, "progressive", NULL);
8439         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8440           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8441               G_TYPE_STRING, "interleaved", NULL);
8442           if (CUR_STREAM (stream)->field_order == 9) {
8443             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8444                 G_TYPE_STRING, "top-field-first", NULL);
8445           } else if (CUR_STREAM (stream)->field_order == 14) {
8446             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8447                 G_TYPE_STRING, "bottom-field-first", NULL);
8448           }
8449         }
8450       }
8451
8452       /* Create incomplete colorimetry here if needed */
8453       if (CUR_STREAM (stream)->colorimetry.range ||
8454           CUR_STREAM (stream)->colorimetry.matrix ||
8455           CUR_STREAM (stream)->colorimetry.transfer
8456           || CUR_STREAM (stream)->colorimetry.primaries) {
8457         gchar *colorimetry =
8458             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8459         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8460             G_TYPE_STRING, colorimetry, NULL);
8461         g_free (colorimetry);
8462       }
8463
8464       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8465         guint par_w = 1, par_h = 1;
8466
8467         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8468           par_w = CUR_STREAM (stream)->par_w;
8469           par_h = CUR_STREAM (stream)->par_h;
8470         }
8471
8472         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8473                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8474                 par_h)) {
8475           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8476         }
8477
8478         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8479             "multiview-mode", G_TYPE_STRING,
8480             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8481             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8482             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8483       }
8484     }
8485   }
8486
8487   else if (stream->subtype == FOURCC_soun) {
8488     if (CUR_STREAM (stream)->caps) {
8489       CUR_STREAM (stream)->caps =
8490           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8491       if (CUR_STREAM (stream)->rate > 0)
8492         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8493             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8494       if (CUR_STREAM (stream)->n_channels > 0)
8495         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8496             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8497       if (CUR_STREAM (stream)->n_channels > 2) {
8498         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8499          * correctly; this is just the minimum we can do - assume
8500          * we don't actually have any channel positions. */
8501         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8502             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8503       }
8504     }
8505   }
8506
8507   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8508     const GstStructure *s;
8509     QtDemuxStream *fps_stream = NULL;
8510     gboolean fps_available = FALSE;
8511
8512     /* CEA608 closed caption tracks are a bit special in that each sample
8513      * can contain CCs for multiple frames, and CCs can be omitted and have to
8514      * be inferred from the duration of the sample then.
8515      *
8516      * As such we take the framerate from the (first) video track here for
8517      * CEA608 as there must be one CC byte pair for every video frame
8518      * according to the spec.
8519      *
8520      * For CEA708 all is fine and there is one sample per frame.
8521      */
8522
8523     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8524     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8525       gint i;
8526
8527       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8528         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8529
8530         if (tmp->subtype == FOURCC_vide) {
8531           fps_stream = tmp;
8532           break;
8533         }
8534       }
8535
8536       if (fps_stream) {
8537         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8538         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8539         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8540       }
8541     } else {
8542       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8543       fps_stream = stream;
8544     }
8545
8546     CUR_STREAM (stream)->caps =
8547         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8548
8549     /* set framerate if calculated framerate is reliable */
8550     if (fps_available) {
8551       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8552           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8553           CUR_STREAM (stream)->fps_d, NULL);
8554     }
8555   }
8556
8557   if (stream->pad) {
8558     GstCaps *prev_caps = NULL;
8559
8560     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8561     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8562     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8563     gst_pad_set_active (stream->pad, TRUE);
8564
8565     gst_pad_use_fixed_caps (stream->pad);
8566
8567     if (stream->protected) {
8568       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8569         GST_ERROR_OBJECT (qtdemux,
8570             "Failed to configure protected stream caps.");
8571         return FALSE;
8572       }
8573     }
8574
8575     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8576         CUR_STREAM (stream)->caps);
8577     if (stream->new_stream) {
8578       GstEvent *event;
8579       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8580
8581       event =
8582           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8583           0);
8584       if (event) {
8585         gst_event_parse_stream_flags (event, &stream_flags);
8586         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8587           qtdemux->have_group_id = TRUE;
8588         else
8589           qtdemux->have_group_id = FALSE;
8590         gst_event_unref (event);
8591       } else if (!qtdemux->have_group_id) {
8592         qtdemux->have_group_id = TRUE;
8593         qtdemux->group_id = gst_util_group_id_next ();
8594       }
8595
8596       stream->new_stream = FALSE;
8597       event = gst_event_new_stream_start (stream->stream_id);
8598       if (qtdemux->have_group_id)
8599         gst_event_set_group_id (event, qtdemux->group_id);
8600       if (stream->disabled)
8601         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8602       if (CUR_STREAM (stream)->sparse) {
8603         stream_flags |= GST_STREAM_FLAG_SPARSE;
8604       } else {
8605         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8606       }
8607       gst_event_set_stream_flags (event, stream_flags);
8608       gst_pad_push_event (stream->pad, event);
8609     }
8610
8611     prev_caps = gst_pad_get_current_caps (stream->pad);
8612
8613     if (CUR_STREAM (stream)->caps) {
8614       if (!prev_caps
8615           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8616         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8617             CUR_STREAM (stream)->caps);
8618         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8619       } else {
8620         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8621       }
8622     } else {
8623       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8624     }
8625
8626     if (prev_caps)
8627       gst_caps_unref (prev_caps);
8628     stream->new_caps = FALSE;
8629   }
8630   return TRUE;
8631 }
8632
8633 static void
8634 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8635     QtDemuxStream * stream)
8636 {
8637   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8638     return;
8639
8640   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8641       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8642   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8643           stream->stsd_entries_length)) {
8644     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8645         (_("This file is invalid and cannot be played.")),
8646         ("New sample description id is out of bounds (%d >= %d)",
8647             stream->stsd_sample_description_id, stream->stsd_entries_length));
8648   } else {
8649     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8650     stream->new_caps = TRUE;
8651   }
8652 }
8653
8654 static gboolean
8655 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8656     QtDemuxStream * stream, GstTagList * list)
8657 {
8658   gboolean ret = TRUE;
8659
8660   if (stream->subtype == FOURCC_vide) {
8661     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8662
8663     stream->pad =
8664         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8665     g_free (name);
8666
8667     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8668       gst_object_unref (stream->pad);
8669       stream->pad = NULL;
8670       ret = FALSE;
8671       goto done;
8672     }
8673
8674     qtdemux->n_video_streams++;
8675   } else if (stream->subtype == FOURCC_soun) {
8676     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8677
8678     stream->pad =
8679         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8680     g_free (name);
8681     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8682       gst_object_unref (stream->pad);
8683       stream->pad = NULL;
8684       ret = FALSE;
8685       goto done;
8686     }
8687     qtdemux->n_audio_streams++;
8688   } else if (stream->subtype == FOURCC_strm) {
8689     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8690   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8691       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8692       || stream->subtype == FOURCC_clcp) {
8693     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8694
8695     stream->pad =
8696         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8697     g_free (name);
8698     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8699       gst_object_unref (stream->pad);
8700       stream->pad = NULL;
8701       ret = FALSE;
8702       goto done;
8703     }
8704     qtdemux->n_sub_streams++;
8705   } else if (CUR_STREAM (stream)->caps) {
8706     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8707
8708     stream->pad =
8709         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8710     g_free (name);
8711     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8712       gst_object_unref (stream->pad);
8713       stream->pad = NULL;
8714       ret = FALSE;
8715       goto done;
8716     }
8717     qtdemux->n_video_streams++;
8718   } else {
8719     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8720     goto done;
8721   }
8722
8723   if (stream->pad) {
8724     GList *l;
8725
8726     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8727         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8728     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8729     GST_OBJECT_LOCK (qtdemux);
8730     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8731     GST_OBJECT_UNLOCK (qtdemux);
8732
8733     if (stream->stream_tags)
8734       gst_tag_list_unref (stream->stream_tags);
8735     stream->stream_tags = list;
8736     list = NULL;
8737     /* global tags go on each pad anyway */
8738     stream->send_global_tags = TRUE;
8739     /* send upstream GST_EVENT_PROTECTION events that were received before
8740        this source pad was created */
8741     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8742       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8743   }
8744 done:
8745   if (list)
8746     gst_tag_list_unref (list);
8747   return ret;
8748 }
8749
8750 /* find next atom with @fourcc starting at @offset */
8751 static GstFlowReturn
8752 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8753     guint64 * length, guint32 fourcc)
8754 {
8755   GstFlowReturn ret;
8756   guint32 lfourcc;
8757   GstBuffer *buf;
8758
8759   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8760       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8761
8762   while (TRUE) {
8763     GstMapInfo map;
8764
8765     buf = NULL;
8766     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8767     if (G_UNLIKELY (ret != GST_FLOW_OK))
8768       goto locate_failed;
8769     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8770       /* likely EOF */
8771       ret = GST_FLOW_EOS;
8772       gst_buffer_unref (buf);
8773       goto locate_failed;
8774     }
8775     gst_buffer_map (buf, &map, GST_MAP_READ);
8776     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8777     gst_buffer_unmap (buf, &map);
8778     gst_buffer_unref (buf);
8779
8780     if (G_UNLIKELY (*length == 0)) {
8781       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8782       ret = GST_FLOW_ERROR;
8783       goto locate_failed;
8784     }
8785
8786     if (lfourcc == fourcc) {
8787       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8788           *offset);
8789       break;
8790     } else {
8791       GST_LOG_OBJECT (qtdemux,
8792           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8793           GST_FOURCC_ARGS (fourcc), *offset);
8794       *offset += *length;
8795     }
8796   }
8797
8798   return GST_FLOW_OK;
8799
8800 locate_failed:
8801   {
8802     /* might simply have had last one */
8803     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8804     return ret;
8805   }
8806 }
8807
8808 /* should only do something in pull mode */
8809 /* call with OBJECT lock */
8810 static GstFlowReturn
8811 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8812 {
8813   guint64 length, offset;
8814   GstBuffer *buf = NULL;
8815   GstFlowReturn ret = GST_FLOW_OK;
8816   GstFlowReturn res = GST_FLOW_OK;
8817   GstMapInfo map;
8818
8819   offset = qtdemux->moof_offset;
8820   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8821
8822   if (!offset) {
8823     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8824     return GST_FLOW_EOS;
8825   }
8826
8827   /* best not do pull etc with lock held */
8828   GST_OBJECT_UNLOCK (qtdemux);
8829
8830   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8831   if (ret != GST_FLOW_OK)
8832     goto flow_failed;
8833
8834   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8835   if (G_UNLIKELY (ret != GST_FLOW_OK))
8836     goto flow_failed;
8837   gst_buffer_map (buf, &map, GST_MAP_READ);
8838   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8839     gst_buffer_unmap (buf, &map);
8840     gst_buffer_unref (buf);
8841     buf = NULL;
8842     goto parse_failed;
8843   }
8844
8845   gst_buffer_unmap (buf, &map);
8846   gst_buffer_unref (buf);
8847   buf = NULL;
8848
8849   offset += length;
8850   /* look for next moof */
8851   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8852   if (G_UNLIKELY (ret != GST_FLOW_OK))
8853     goto flow_failed;
8854
8855 exit:
8856   GST_OBJECT_LOCK (qtdemux);
8857
8858   qtdemux->moof_offset = offset;
8859
8860   return res;
8861
8862 parse_failed:
8863   {
8864     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8865     offset = 0;
8866     res = GST_FLOW_ERROR;
8867     goto exit;
8868   }
8869 flow_failed:
8870   {
8871     /* maybe upstream temporarily flushing */
8872     if (ret != GST_FLOW_FLUSHING) {
8873       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8874       offset = 0;
8875     } else {
8876       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8877       /* resume at current position next time */
8878     }
8879     res = ret;
8880     goto exit;
8881   }
8882 }
8883
8884 static void
8885 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
8886 {
8887   guint i;
8888   guint32 num_chunks;
8889   gint32 stts_duration;
8890   GstByteWriter stsc, stts, stsz;
8891
8892   /* Each sample has a different size, which we don't support for merging */
8893   if (stream->sample_size == 0) {
8894     GST_DEBUG_OBJECT (qtdemux,
8895         "Not all samples have the same size, not merging");
8896     return;
8897   }
8898
8899   /* The stream has a ctts table, we don't support that */
8900   if (stream->ctts_present) {
8901     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
8902     return;
8903   }
8904
8905   /* If there's a sync sample table also ignore this stream */
8906   if (stream->stps_present || stream->stss_present) {
8907     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
8908     return;
8909   }
8910
8911   /* If chunks are considered samples already ignore this stream */
8912   if (stream->chunks_are_samples) {
8913     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
8914     return;
8915   }
8916
8917   /* Require that all samples have the same duration */
8918   if (stream->n_sample_times > 1) {
8919     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
8920     return;
8921   }
8922
8923   /* Parse the stts to get the sample duration and number of samples */
8924   gst_byte_reader_skip_unchecked (&stream->stts, 4);
8925   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8926
8927   /* Parse the number of chunks from the stco manually because the
8928    * reader is already behind that */
8929   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
8930
8931   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
8932       num_chunks);
8933
8934   /* Now parse stsc, convert chunks into single samples and generate a
8935    * new stsc, stts and stsz from this information */
8936   gst_byte_writer_init (&stsc);
8937   gst_byte_writer_init (&stts);
8938   gst_byte_writer_init (&stsz);
8939
8940   /* Note: we skip fourccs, size, version, flags and other fields of the new
8941    * atoms as the byte readers with them are already behind that position
8942    * anyway and only update the values of those inside the stream directly.
8943    */
8944   stream->n_sample_times = 0;
8945   stream->n_samples = 0;
8946   for (i = 0; i < stream->n_samples_per_chunk; i++) {
8947     guint j;
8948     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
8949
8950     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8951     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8952     sample_description_id =
8953         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8954
8955     if (i == stream->n_samples_per_chunk - 1) {
8956       /* +1 because first_chunk is 1-based */
8957       last_chunk = num_chunks + 1;
8958     } else {
8959       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8960     }
8961
8962     GST_DEBUG_OBJECT (qtdemux,
8963         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
8964         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
8965
8966     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
8967     /* One sample in this chunk */
8968     gst_byte_writer_put_uint32_be (&stsc, 1);
8969     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
8970
8971     /* For each chunk write a stts and stsz entry now */
8972     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
8973     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
8974     for (j = first_chunk; j < last_chunk; j++) {
8975       gst_byte_writer_put_uint32_be (&stsz,
8976           stream->sample_size * samples_per_chunk);
8977     }
8978
8979     stream->n_sample_times += 1;
8980     stream->n_samples += last_chunk - first_chunk;
8981   }
8982
8983   g_assert_cmpint (stream->n_samples, ==, num_chunks);
8984
8985   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
8986       stream->n_samples, stream->n_sample_times);
8987
8988   /* We don't have a fixed sample size anymore */
8989   stream->sample_size = 0;
8990
8991   /* Free old data for the atoms */
8992   g_free ((gpointer) stream->stsz.data);
8993   stream->stsz.data = NULL;
8994   g_free ((gpointer) stream->stsc.data);
8995   stream->stsc.data = NULL;
8996   g_free ((gpointer) stream->stts.data);
8997   stream->stts.data = NULL;
8998
8999   /* Store new data and replace byte readers */
9000   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9001   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9002   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9003   stream->stts.size = gst_byte_writer_get_size (&stts);
9004   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9005   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9006   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9007   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9008   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9009 }
9010
9011 /* initialise bytereaders for stbl sub-atoms */
9012 static gboolean
9013 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9014 {
9015   stream->stbl_index = -1;      /* no samples have yet been parsed */
9016   stream->sample_index = -1;
9017
9018   /* time-to-sample atom */
9019   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9020     goto corrupt_file;
9021
9022   /* copy atom data into a new buffer for later use */
9023   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
9024
9025   /* skip version + flags */
9026   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9027       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9028     goto corrupt_file;
9029   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9030
9031   /* make sure there's enough data */
9032   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9033     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9034     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9035         stream->n_sample_times);
9036     if (!stream->n_sample_times)
9037       goto corrupt_file;
9038   }
9039
9040   /* sync sample atom */
9041   stream->stps_present = FALSE;
9042   if ((stream->stss_present =
9043           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9044               &stream->stss) ? TRUE : FALSE) == TRUE) {
9045     /* copy atom data into a new buffer for later use */
9046     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
9047
9048     /* skip version + flags */
9049     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9050         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9051       goto corrupt_file;
9052
9053     if (stream->n_sample_syncs) {
9054       /* make sure there's enough data */
9055       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9056         goto corrupt_file;
9057     }
9058
9059     /* partial sync sample atom */
9060     if ((stream->stps_present =
9061             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9062                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9063       /* copy atom data into a new buffer for later use */
9064       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
9065
9066       /* skip version + flags */
9067       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9068           !gst_byte_reader_get_uint32_be (&stream->stps,
9069               &stream->n_sample_partial_syncs))
9070         goto corrupt_file;
9071
9072       /* if there are no entries, the stss table contains the real
9073        * sync samples */
9074       if (stream->n_sample_partial_syncs) {
9075         /* make sure there's enough data */
9076         if (!qt_atom_parser_has_chunks (&stream->stps,
9077                 stream->n_sample_partial_syncs, 4))
9078           goto corrupt_file;
9079       }
9080     }
9081   }
9082
9083   /* sample size */
9084   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9085     goto no_samples;
9086
9087   /* copy atom data into a new buffer for later use */
9088   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
9089
9090   /* skip version + flags */
9091   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9092       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9093     goto corrupt_file;
9094
9095   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9096     goto corrupt_file;
9097
9098   if (!stream->n_samples)
9099     goto no_samples;
9100
9101   /* sample-to-chunk atom */
9102   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9103     goto corrupt_file;
9104
9105   /* copy atom data into a new buffer for later use */
9106   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
9107
9108   /* skip version + flags */
9109   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9110       !gst_byte_reader_get_uint32_be (&stream->stsc,
9111           &stream->n_samples_per_chunk))
9112     goto corrupt_file;
9113
9114   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9115       stream->n_samples_per_chunk);
9116
9117   /* make sure there's enough data */
9118   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9119           12))
9120     goto corrupt_file;
9121
9122
9123   /* chunk offset */
9124   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9125     stream->co_size = sizeof (guint32);
9126   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9127           &stream->stco))
9128     stream->co_size = sizeof (guint64);
9129   else
9130     goto corrupt_file;
9131
9132   /* copy atom data into a new buffer for later use */
9133   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
9134
9135   /* skip version + flags */
9136   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9137     goto corrupt_file;
9138
9139   /* chunks_are_samples == TRUE means treat chunks as samples */
9140   stream->chunks_are_samples = stream->sample_size
9141       && !CUR_STREAM (stream)->sampled;
9142   if (stream->chunks_are_samples) {
9143     /* treat chunks as samples */
9144     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9145       goto corrupt_file;
9146   } else {
9147     /* skip number of entries */
9148     if (!gst_byte_reader_skip (&stream->stco, 4))
9149       goto corrupt_file;
9150
9151     /* make sure there are enough data in the stsz atom */
9152     if (!stream->sample_size) {
9153       /* different sizes for each sample */
9154       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9155         goto corrupt_file;
9156     }
9157   }
9158
9159   /* composition time-to-sample */
9160   if ((stream->ctts_present =
9161           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9162               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9163     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9164
9165     /* copy atom data into a new buffer for later use */
9166     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
9167
9168     /* skip version + flags */
9169     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9170         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9171             &stream->n_composition_times))
9172       goto corrupt_file;
9173
9174     /* make sure there's enough data */
9175     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9176             4 + 4))
9177       goto corrupt_file;
9178
9179     /* This is optional, if missing we iterate the ctts */
9180     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9181       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9182           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9183         g_free ((gpointer) cslg.data);
9184         goto corrupt_file;
9185       }
9186     } else {
9187       gint32 cslg_least = 0;
9188       guint num_entries, pos;
9189       gint i;
9190
9191       pos = gst_byte_reader_get_pos (&stream->ctts);
9192       num_entries = stream->n_composition_times;
9193
9194       stream->cslg_shift = 0;
9195
9196       for (i = 0; i < num_entries; i++) {
9197         gint32 offset;
9198
9199         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9200         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9201         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9202          * slightly inaccurate PTS could be more usable than corrupted one */
9203         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9204           GST_WARNING_OBJECT (qtdemux,
9205               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9206               " larger than duration %" G_GUINT64_FORMAT,
9207               offset, stream->duration);
9208
9209           stream->cslg_shift = 0;
9210           stream->ctts_present = FALSE;
9211           goto done;
9212         }
9213
9214         if (offset < cslg_least)
9215           cslg_least = offset;
9216       }
9217
9218       if (cslg_least < 0)
9219         stream->cslg_shift = ABS (cslg_least);
9220       else
9221         stream->cslg_shift = 0;
9222
9223       /* reset the reader so we can generate sample table */
9224       gst_byte_reader_set_pos (&stream->ctts, pos);
9225     }
9226   } else {
9227     /* Ensure the cslg_shift value is consistent so we can use it
9228      * unconditionally to produce TS and Segment */
9229     stream->cslg_shift = 0;
9230   }
9231
9232   /* For raw audio streams especially we might want to merge the samples
9233    * to not output one audio sample per buffer. We're doing this here
9234    * before allocating the sample tables so that from this point onwards
9235    * the number of container samples are static */
9236   if (stream->min_buffer_size > 0) {
9237     qtdemux_merge_sample_table (qtdemux, stream);
9238   }
9239
9240 done:
9241   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9242       stream->n_samples, (guint) sizeof (QtDemuxSample),
9243       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9244
9245   if (stream->n_samples >=
9246       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9247     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9248         "be larger than %uMB (broken file?)", stream->n_samples,
9249         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9250     return FALSE;
9251   }
9252
9253   g_assert (stream->samples == NULL);
9254   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9255   if (!stream->samples) {
9256     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9257         stream->n_samples);
9258     return FALSE;
9259   }
9260
9261   return TRUE;
9262
9263 corrupt_file:
9264   {
9265     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9266         (_("This file is corrupt and cannot be played.")), (NULL));
9267     return FALSE;
9268   }
9269 no_samples:
9270   {
9271     gst_qtdemux_stbl_free (stream);
9272     if (!qtdemux->fragmented) {
9273       /* not quite good */
9274       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9275       return FALSE;
9276     } else {
9277       /* may pick up samples elsewhere */
9278       return TRUE;
9279     }
9280   }
9281 }
9282
9283 /* collect samples from the next sample to be parsed up to sample @n for @stream
9284  * by reading the info from @stbl
9285  *
9286  * This code can be executed from both the streaming thread and the seeking
9287  * thread so it takes the object lock to protect itself
9288  */
9289 static gboolean
9290 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9291 {
9292   gint i, j, k;
9293   QtDemuxSample *samples, *first, *cur, *last;
9294   guint32 n_samples_per_chunk;
9295   guint32 n_samples;
9296
9297   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9298       GST_FOURCC_FORMAT ", pad %s",
9299       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9300       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9301
9302   n_samples = stream->n_samples;
9303
9304   if (n >= n_samples)
9305     goto out_of_samples;
9306
9307   GST_OBJECT_LOCK (qtdemux);
9308   if (n <= stream->stbl_index)
9309     goto already_parsed;
9310
9311   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9312
9313   if (!stream->stsz.data) {
9314     /* so we already parsed and passed all the moov samples;
9315      * onto fragmented ones */
9316     g_assert (qtdemux->fragmented);
9317     goto done;
9318   }
9319
9320   /* pointer to the sample table */
9321   samples = stream->samples;
9322
9323   /* starts from -1, moves to the next sample index to parse */
9324   stream->stbl_index++;
9325
9326   /* keep track of the first and last sample to fill */
9327   first = &samples[stream->stbl_index];
9328   last = &samples[n];
9329
9330   if (!stream->chunks_are_samples) {
9331     /* set the sample sizes */
9332     if (stream->sample_size == 0) {
9333       /* different sizes for each sample */
9334       for (cur = first; cur <= last; cur++) {
9335         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9336         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9337             (guint) (cur - samples), cur->size);
9338       }
9339     } else {
9340       /* samples have the same size */
9341       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9342       for (cur = first; cur <= last; cur++)
9343         cur->size = stream->sample_size;
9344     }
9345   }
9346
9347   n_samples_per_chunk = stream->n_samples_per_chunk;
9348   cur = first;
9349
9350   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9351     guint32 last_chunk;
9352
9353     if (stream->stsc_chunk_index >= stream->last_chunk
9354         || stream->stsc_chunk_index < stream->first_chunk) {
9355       stream->first_chunk =
9356           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9357       stream->samples_per_chunk =
9358           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9359       /* starts from 1 */
9360       stream->stsd_sample_description_id =
9361           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9362
9363       /* chunk numbers are counted from 1 it seems */
9364       if (G_UNLIKELY (stream->first_chunk == 0))
9365         goto corrupt_file;
9366
9367       --stream->first_chunk;
9368
9369       /* the last chunk of each entry is calculated by taking the first chunk
9370        * of the next entry; except if there is no next, where we fake it with
9371        * INT_MAX */
9372       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9373         stream->last_chunk = G_MAXUINT32;
9374       } else {
9375         stream->last_chunk =
9376             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9377         if (G_UNLIKELY (stream->last_chunk == 0))
9378           goto corrupt_file;
9379
9380         --stream->last_chunk;
9381       }
9382
9383       GST_LOG_OBJECT (qtdemux,
9384           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9385           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9386           stream->samples_per_chunk, stream->stsd_sample_description_id);
9387
9388       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9389         goto corrupt_file;
9390
9391       if (stream->last_chunk != G_MAXUINT32) {
9392         if (!qt_atom_parser_peek_sub (&stream->stco,
9393                 stream->first_chunk * stream->co_size,
9394                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9395                 &stream->co_chunk))
9396           goto corrupt_file;
9397
9398       } else {
9399         stream->co_chunk = stream->stco;
9400         if (!gst_byte_reader_skip (&stream->co_chunk,
9401                 stream->first_chunk * stream->co_size))
9402           goto corrupt_file;
9403       }
9404
9405       stream->stsc_chunk_index = stream->first_chunk;
9406     }
9407
9408     last_chunk = stream->last_chunk;
9409
9410     if (stream->chunks_are_samples) {
9411       cur = &samples[stream->stsc_chunk_index];
9412
9413       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9414         if (j > n) {
9415           /* save state */
9416           stream->stsc_chunk_index = j;
9417           goto done;
9418         }
9419
9420         cur->offset =
9421             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9422             stream->co_size);
9423
9424         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9425             "%" G_GUINT64_FORMAT, j, cur->offset);
9426
9427         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9428             CUR_STREAM (stream)->bytes_per_frame > 0) {
9429           cur->size =
9430               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9431               CUR_STREAM (stream)->samples_per_frame *
9432               CUR_STREAM (stream)->bytes_per_frame;
9433         } else {
9434           cur->size = stream->samples_per_chunk;
9435         }
9436
9437         GST_DEBUG_OBJECT (qtdemux,
9438             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9439             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9440                     stream->stco_sample_index)), cur->size);
9441
9442         cur->timestamp = stream->stco_sample_index;
9443         cur->duration = stream->samples_per_chunk;
9444         cur->keyframe = TRUE;
9445         cur++;
9446
9447         stream->stco_sample_index += stream->samples_per_chunk;
9448       }
9449       stream->stsc_chunk_index = j;
9450     } else {
9451       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9452         guint32 samples_per_chunk;
9453         guint64 chunk_offset;
9454
9455         if (!stream->stsc_sample_index
9456             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9457                 &stream->chunk_offset))
9458           goto corrupt_file;
9459
9460         samples_per_chunk = stream->samples_per_chunk;
9461         chunk_offset = stream->chunk_offset;
9462
9463         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9464           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9465               G_GUINT64_FORMAT " and size %d",
9466               (guint) (cur - samples), chunk_offset, cur->size);
9467
9468           cur->offset = chunk_offset;
9469           chunk_offset += cur->size;
9470           cur++;
9471
9472           if (G_UNLIKELY (cur > last)) {
9473             /* save state */
9474             stream->stsc_sample_index = k + 1;
9475             stream->chunk_offset = chunk_offset;
9476             stream->stsc_chunk_index = j;
9477             goto done2;
9478           }
9479         }
9480         stream->stsc_sample_index = 0;
9481       }
9482       stream->stsc_chunk_index = j;
9483     }
9484     stream->stsc_index++;
9485   }
9486
9487   if (stream->chunks_are_samples)
9488     goto ctts;
9489 done2:
9490   {
9491     guint32 n_sample_times;
9492
9493     n_sample_times = stream->n_sample_times;
9494     cur = first;
9495
9496     for (i = stream->stts_index; i < n_sample_times; i++) {
9497       guint32 stts_samples;
9498       gint32 stts_duration;
9499       gint64 stts_time;
9500
9501       if (stream->stts_sample_index >= stream->stts_samples
9502           || !stream->stts_sample_index) {
9503
9504         stream->stts_samples =
9505             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9506         stream->stts_duration =
9507             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9508
9509         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9510             i, stream->stts_samples, stream->stts_duration);
9511
9512         stream->stts_sample_index = 0;
9513       }
9514
9515       stts_samples = stream->stts_samples;
9516       stts_duration = stream->stts_duration;
9517       stts_time = stream->stts_time;
9518
9519       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9520         GST_DEBUG_OBJECT (qtdemux,
9521             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9522             (guint) (cur - samples), j,
9523             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9524
9525         cur->timestamp = stts_time;
9526         cur->duration = stts_duration;
9527
9528         /* avoid 32-bit wrap-around,
9529          * but still mind possible 'negative' duration */
9530         stts_time += (gint64) stts_duration;
9531         cur++;
9532
9533         if (G_UNLIKELY (cur > last)) {
9534           /* save values */
9535           stream->stts_time = stts_time;
9536           stream->stts_sample_index = j + 1;
9537           if (stream->stts_sample_index >= stream->stts_samples)
9538             stream->stts_index++;
9539           goto done3;
9540         }
9541       }
9542       stream->stts_sample_index = 0;
9543       stream->stts_time = stts_time;
9544       stream->stts_index++;
9545     }
9546     /* fill up empty timestamps with the last timestamp, this can happen when
9547      * the last samples do not decode and so we don't have timestamps for them.
9548      * We however look at the last timestamp to estimate the track length so we
9549      * need something in here. */
9550     for (; cur < last; cur++) {
9551       GST_DEBUG_OBJECT (qtdemux,
9552           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9553           (guint) (cur - samples),
9554           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9555       cur->timestamp = stream->stts_time;
9556       cur->duration = -1;
9557     }
9558   }
9559 done3:
9560   {
9561     /* sample sync, can be NULL */
9562     if (stream->stss_present == TRUE) {
9563       guint32 n_sample_syncs;
9564
9565       n_sample_syncs = stream->n_sample_syncs;
9566
9567       if (!n_sample_syncs) {
9568         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9569         stream->all_keyframe = TRUE;
9570       } else {
9571         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9572           /* note that the first sample is index 1, not 0 */
9573           guint32 index;
9574
9575           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9576
9577           if (G_LIKELY (index > 0 && index <= n_samples)) {
9578             index -= 1;
9579             samples[index].keyframe = TRUE;
9580             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9581             /* and exit if we have enough samples */
9582             if (G_UNLIKELY (index >= n)) {
9583               i++;
9584               break;
9585             }
9586           }
9587         }
9588         /* save state */
9589         stream->stss_index = i;
9590       }
9591
9592       /* stps marks partial sync frames like open GOP I-Frames */
9593       if (stream->stps_present == TRUE) {
9594         guint32 n_sample_partial_syncs;
9595
9596         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9597
9598         /* if there are no entries, the stss table contains the real
9599          * sync samples */
9600         if (n_sample_partial_syncs) {
9601           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9602             /* note that the first sample is index 1, not 0 */
9603             guint32 index;
9604
9605             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9606
9607             if (G_LIKELY (index > 0 && index <= n_samples)) {
9608               index -= 1;
9609               samples[index].keyframe = TRUE;
9610               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9611               /* and exit if we have enough samples */
9612               if (G_UNLIKELY (index >= n)) {
9613                 i++;
9614                 break;
9615               }
9616             }
9617           }
9618           /* save state */
9619           stream->stps_index = i;
9620         }
9621       }
9622     } else {
9623       /* no stss, all samples are keyframes */
9624       stream->all_keyframe = TRUE;
9625       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9626     }
9627   }
9628
9629 ctts:
9630   /* composition time to sample */
9631   if (stream->ctts_present == TRUE) {
9632     guint32 n_composition_times;
9633     guint32 ctts_count;
9634     gint32 ctts_soffset;
9635
9636     /* Fill in the pts_offsets */
9637     cur = first;
9638     n_composition_times = stream->n_composition_times;
9639
9640     for (i = stream->ctts_index; i < n_composition_times; i++) {
9641       if (stream->ctts_sample_index >= stream->ctts_count
9642           || !stream->ctts_sample_index) {
9643         stream->ctts_count =
9644             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9645         stream->ctts_soffset =
9646             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9647         stream->ctts_sample_index = 0;
9648       }
9649
9650       ctts_count = stream->ctts_count;
9651       ctts_soffset = stream->ctts_soffset;
9652
9653       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9654         cur->pts_offset = ctts_soffset;
9655         cur++;
9656
9657         if (G_UNLIKELY (cur > last)) {
9658           /* save state */
9659           stream->ctts_sample_index = j + 1;
9660           goto done;
9661         }
9662       }
9663       stream->ctts_sample_index = 0;
9664       stream->ctts_index++;
9665     }
9666   }
9667 done:
9668   stream->stbl_index = n;
9669   /* if index has been completely parsed, free data that is no-longer needed */
9670   if (n + 1 == stream->n_samples) {
9671     gst_qtdemux_stbl_free (stream);
9672     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9673     if (qtdemux->pullbased) {
9674       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9675       while (n + 1 == stream->n_samples)
9676         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9677           break;
9678     }
9679   }
9680   GST_OBJECT_UNLOCK (qtdemux);
9681
9682   return TRUE;
9683
9684   /* SUCCESS */
9685 already_parsed:
9686   {
9687     GST_LOG_OBJECT (qtdemux,
9688         "Tried to parse up to sample %u but this sample has already been parsed",
9689         n);
9690     /* if fragmented, there may be more */
9691     if (qtdemux->fragmented && n == stream->stbl_index)
9692       goto done;
9693     GST_OBJECT_UNLOCK (qtdemux);
9694     return TRUE;
9695   }
9696   /* ERRORS */
9697 out_of_samples:
9698   {
9699     GST_LOG_OBJECT (qtdemux,
9700         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9701         stream->n_samples);
9702     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9703         (_("This file is corrupt and cannot be played.")), (NULL));
9704     return FALSE;
9705   }
9706 corrupt_file:
9707   {
9708     GST_OBJECT_UNLOCK (qtdemux);
9709     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9710         (_("This file is corrupt and cannot be played.")), (NULL));
9711     return FALSE;
9712   }
9713 }
9714
9715 /* collect all segment info for @stream.
9716  */
9717 static gboolean
9718 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9719     GNode * trak)
9720 {
9721   GNode *edts;
9722   /* accept edts if they contain gaps at start and there is only
9723    * one media segment */
9724   gboolean allow_pushbased_edts = TRUE;
9725   gint media_segments_count = 0;
9726
9727   /* parse and prepare segment info from the edit list */
9728   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9729   stream->n_segments = 0;
9730   stream->segments = NULL;
9731   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9732     GNode *elst;
9733     gint n_segments;
9734     gint segment_number, entry_size;
9735     guint64 time;
9736     GstClockTime stime;
9737     const guint8 *buffer;
9738     guint8 version;
9739     guint32 size;
9740
9741     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9742     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9743       goto done;
9744
9745     buffer = elst->data;
9746
9747     size = QT_UINT32 (buffer);
9748     /* version, flags, n_segments */
9749     if (size < 16) {
9750       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9751       goto done;
9752     }
9753     version = QT_UINT8 (buffer + 8);
9754     entry_size = (version == 1) ? 20 : 12;
9755
9756     n_segments = QT_UINT32 (buffer + 12);
9757
9758     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9759       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9760       goto done;
9761     }
9762
9763     /* we might allocate a bit too much, at least allocate 1 segment */
9764     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9765
9766     /* segments always start from 0 */
9767     time = 0;
9768     stime = 0;
9769     buffer += 16;
9770     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9771       guint64 duration;
9772       guint64 media_time;
9773       gboolean empty_edit = FALSE;
9774       QtDemuxSegment *segment;
9775       guint32 rate_int;
9776       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9777
9778       if (version == 1) {
9779         media_time = QT_UINT64 (buffer + 8);
9780         duration = QT_UINT64 (buffer);
9781         if (media_time == G_MAXUINT64)
9782           empty_edit = TRUE;
9783       } else {
9784         media_time = QT_UINT32 (buffer + 4);
9785         duration = QT_UINT32 (buffer);
9786         if (media_time == G_MAXUINT32)
9787           empty_edit = TRUE;
9788       }
9789
9790       if (!empty_edit)
9791         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9792
9793       segment = &stream->segments[segment_number];
9794
9795       /* time and duration expressed in global timescale */
9796       segment->time = stime;
9797       if (duration != 0 || empty_edit) {
9798         /* edge case: empty edits with duration=zero are treated here.
9799          * (files should not have these anyway). */
9800
9801         /* add non scaled values so we don't cause roundoff errors */
9802         time += duration;
9803         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9804         segment->duration = stime - segment->time;
9805       } else {
9806         /* zero duration does not imply media_start == media_stop
9807          * but, only specify media_start. The edit ends with the track. */
9808         stime = segment->duration = GST_CLOCK_TIME_NONE;
9809         /* Don't allow more edits after this one. */
9810         n_segments = segment_number + 1;
9811       }
9812       segment->stop_time = stime;
9813
9814       segment->trak_media_start = media_time;
9815       /* media_time expressed in stream timescale */
9816       if (!empty_edit) {
9817         segment->media_start = media_start;
9818         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9819             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9820         media_segments_count++;
9821       } else {
9822         segment->media_start = GST_CLOCK_TIME_NONE;
9823         segment->media_stop = GST_CLOCK_TIME_NONE;
9824       }
9825       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9826
9827       if (rate_int <= 1) {
9828         /* 0 is not allowed, some programs write 1 instead of the floating point
9829          * value */
9830         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9831             rate_int);
9832         segment->rate = 1;
9833       } else {
9834         segment->rate = rate_int / 65536.0;
9835       }
9836
9837       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9838           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9839           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9840           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9841           segment_number, GST_TIME_ARGS (segment->time),
9842           GST_TIME_ARGS (segment->duration),
9843           GST_TIME_ARGS (segment->media_start), media_time,
9844           GST_TIME_ARGS (segment->media_stop),
9845           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9846           stream->timescale);
9847       if (segment->stop_time > qtdemux->segment.stop &&
9848           !qtdemux->upstream_format_is_time) {
9849         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9850             " extends to %" GST_TIME_FORMAT
9851             " past the end of the declared movie duration %" GST_TIME_FORMAT
9852             " movie segment will be extended", segment_number,
9853             GST_TIME_ARGS (segment->stop_time),
9854             GST_TIME_ARGS (qtdemux->segment.stop));
9855         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9856       }
9857
9858       buffer += entry_size;
9859     }
9860     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9861     stream->n_segments = n_segments;
9862     if (media_segments_count != 1)
9863       allow_pushbased_edts = FALSE;
9864   }
9865 done:
9866
9867   /* push based does not handle segments, so act accordingly here,
9868    * and warn if applicable */
9869   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9870     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9871     /* remove and use default one below, we stream like it anyway */
9872     g_free (stream->segments);
9873     stream->segments = NULL;
9874     stream->n_segments = 0;
9875   }
9876
9877   /* no segments, create one to play the complete trak */
9878   if (stream->n_segments == 0) {
9879     GstClockTime stream_duration =
9880         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9881
9882     if (stream->segments == NULL)
9883       stream->segments = g_new (QtDemuxSegment, 1);
9884
9885     /* represent unknown our way */
9886     if (stream_duration == 0)
9887       stream_duration = GST_CLOCK_TIME_NONE;
9888
9889     stream->segments[0].time = 0;
9890     stream->segments[0].stop_time = stream_duration;
9891     stream->segments[0].duration = stream_duration;
9892     stream->segments[0].media_start = 0;
9893     stream->segments[0].media_stop = stream_duration;
9894     stream->segments[0].rate = 1.0;
9895     stream->segments[0].trak_media_start = 0;
9896
9897     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9898         GST_TIME_ARGS (stream_duration));
9899     stream->n_segments = 1;
9900     stream->dummy_segment = TRUE;
9901   }
9902   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9903
9904   return TRUE;
9905 }
9906
9907 /*
9908  * Parses the stsd atom of a svq3 trak looking for
9909  * the SMI and gama atoms.
9910  */
9911 static void
9912 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9913     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9914 {
9915   const guint8 *_gamma = NULL;
9916   GstBuffer *_seqh = NULL;
9917   const guint8 *stsd_data = stsd_entry_data;
9918   guint32 length = QT_UINT32 (stsd_data);
9919   guint16 version;
9920
9921   if (length < 32) {
9922     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9923     goto end;
9924   }
9925
9926   stsd_data += 16;
9927   length -= 16;
9928   version = QT_UINT16 (stsd_data);
9929   if (version == 3) {
9930     if (length >= 70) {
9931       length -= 70;
9932       stsd_data += 70;
9933       while (length > 8) {
9934         guint32 fourcc, size;
9935         const guint8 *data;
9936         size = QT_UINT32 (stsd_data);
9937         fourcc = QT_FOURCC (stsd_data + 4);
9938         data = stsd_data + 8;
9939
9940         if (size == 0) {
9941           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9942               "svq3 atom parsing");
9943           goto end;
9944         }
9945
9946         switch (fourcc) {
9947           case FOURCC_gama:{
9948             if (size == 12) {
9949               _gamma = data;
9950             } else {
9951               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9952                   " for gama atom, expected 12", size);
9953             }
9954             break;
9955           }
9956           case FOURCC_SMI_:{
9957             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9958               guint32 seqh_size;
9959               if (_seqh != NULL) {
9960                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9961                     " found, ignoring");
9962               } else {
9963                 seqh_size = QT_UINT32 (data + 4);
9964                 if (seqh_size > 0) {
9965                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9966                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9967                 }
9968               }
9969             }
9970             break;
9971           }
9972           default:{
9973             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9974                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9975           }
9976         }
9977
9978         if (size <= length) {
9979           length -= size;
9980           stsd_data += size;
9981         }
9982       }
9983     } else {
9984       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9985     }
9986   } else {
9987     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9988         G_GUINT16_FORMAT, version);
9989     goto end;
9990   }
9991
9992 end:
9993   if (gamma) {
9994     *gamma = _gamma;
9995   }
9996   if (seqh) {
9997     *seqh = _seqh;
9998   } else if (_seqh) {
9999     gst_buffer_unref (_seqh);
10000   }
10001 }
10002
10003 static gchar *
10004 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10005 {
10006   GNode *dinf;
10007   GstByteReader dref;
10008   gchar *uri = NULL;
10009
10010   /*
10011    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10012    * atom that might contain a 'data' atom with the rtsp uri.
10013    * This case was reported in bug #597497, some info about
10014    * the hndl atom can be found in TN1195
10015    */
10016   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10017   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10018
10019   if (dinf) {
10020     guint32 dref_num_entries = 0;
10021     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10022         gst_byte_reader_skip (&dref, 4) &&
10023         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10024       gint i;
10025
10026       /* search dref entries for hndl atom */
10027       for (i = 0; i < dref_num_entries; i++) {
10028         guint32 size = 0, type;
10029         guint8 string_len = 0;
10030         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10031             qt_atom_parser_get_fourcc (&dref, &type)) {
10032           if (type == FOURCC_hndl) {
10033             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10034
10035             /* skip data reference handle bytes and the
10036              * following pascal string and some extra 4
10037              * bytes I have no idea what are */
10038             if (!gst_byte_reader_skip (&dref, 4) ||
10039                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10040                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10041               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10042               break;
10043             }
10044
10045             /* iterate over the atoms to find the data atom */
10046             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10047               guint32 atom_size;
10048               guint32 atom_type;
10049
10050               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10051                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10052                 if (atom_type == FOURCC_data) {
10053                   const guint8 *uri_aux = NULL;
10054
10055                   /* found the data atom that might contain the rtsp uri */
10056                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10057                       "hndl atom, interpreting it as an URI");
10058                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10059                           &uri_aux)) {
10060                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10061                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10062                     else
10063                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10064                           "didn't contain a rtsp address");
10065                   } else {
10066                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10067                         "atom contents");
10068                   }
10069                   break;
10070                 }
10071                 /* skipping to the next entry */
10072                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10073                   break;
10074               } else {
10075                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10076                     "atom header");
10077                 break;
10078               }
10079             }
10080             break;
10081           }
10082           /* skip to the next entry */
10083           if (!gst_byte_reader_skip (&dref, size - 8))
10084             break;
10085         } else {
10086           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10087         }
10088       }
10089       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10090     }
10091   }
10092   return uri;
10093 }
10094
10095 #define AMR_NB_ALL_MODES        0x81ff
10096 #define AMR_WB_ALL_MODES        0x83ff
10097 static guint
10098 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10099 {
10100   /* The 'damr' atom is of the form:
10101    *
10102    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10103    *    32 b       8 b          16 b           8 b                 8 b
10104    *
10105    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10106    * represents the highest mode used in the stream (and thus the maximum
10107    * bitrate), with a couple of special cases as seen below.
10108    */
10109
10110   /* Map of frame type ID -> bitrate */
10111   static const guint nb_bitrates[] = {
10112     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10113   };
10114   static const guint wb_bitrates[] = {
10115     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10116   };
10117   GstMapInfo map;
10118   gsize max_mode;
10119   guint16 mode_set;
10120
10121   gst_buffer_map (buf, &map, GST_MAP_READ);
10122
10123   if (map.size != 0x11) {
10124     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10125     goto bad_data;
10126   }
10127
10128   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10129     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10130         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10131     goto bad_data;
10132   }
10133
10134   mode_set = QT_UINT16 (map.data + 13);
10135
10136   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10137     max_mode = 7 + (wb ? 1 : 0);
10138   else
10139     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10140     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10141
10142   if (max_mode == -1) {
10143     GST_DEBUG ("No mode indication was found (mode set) = %x",
10144         (guint) mode_set);
10145     goto bad_data;
10146   }
10147
10148   gst_buffer_unmap (buf, &map);
10149   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10150
10151 bad_data:
10152   gst_buffer_unmap (buf, &map);
10153   return 0;
10154 }
10155
10156 static gboolean
10157 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10158     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10159 {
10160   /*
10161    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10162    * [0 1 2]
10163    * [3 4 5]
10164    * [6 7 8]
10165    */
10166
10167   if (gst_byte_reader_get_remaining (reader) < 36)
10168     return FALSE;
10169
10170   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10171   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10172   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10173   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10174   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10175   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10176   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10177   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10178   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10179
10180   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10181   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10182       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10183       matrix[2] & 0xFF);
10184   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10185       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10186       matrix[5] & 0xFF);
10187   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10188       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10189       matrix[8] & 0xFF);
10190
10191   return TRUE;
10192 }
10193
10194 static void
10195 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10196     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10197 {
10198
10199 /* [a b c]
10200  * [d e f]
10201  * [g h i]
10202  *
10203  * This macro will only compare value abdegh, it expects cfi to have already
10204  * been checked
10205  */
10206 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10207                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10208
10209   /* only handle the cases where the last column has standard values */
10210   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10211     const gchar *rotation_tag = NULL;
10212
10213     /* no rotation needed */
10214     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10215       /* NOP */
10216     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10217       rotation_tag = "rotate-90";
10218     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10219       rotation_tag = "rotate-180";
10220     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10221       rotation_tag = "rotate-270";
10222     } else {
10223       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10224     }
10225
10226     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10227         GST_STR_NULL (rotation_tag));
10228     if (rotation_tag != NULL) {
10229       if (*taglist == NULL)
10230         *taglist = gst_tag_list_new_empty ();
10231       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10232           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10233     }
10234   } else {
10235     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10236   }
10237 }
10238
10239 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10240  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10241  * Common Encryption (cenc), the function will also parse the tenc box (defined
10242  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10243  * (typically an enc[v|a|t|s] sample entry); the function will set
10244  * @original_fmt to the fourcc of the original unencrypted stream format.
10245  * Returns TRUE if successful; FALSE otherwise. */
10246 static gboolean
10247 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10248     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10249 {
10250   GNode *sinf;
10251   GNode *frma;
10252   GNode *schm;
10253   GNode *schi;
10254   QtDemuxCencSampleSetInfo *info;
10255   GNode *tenc;
10256   const guint8 *tenc_data;
10257
10258   g_return_val_if_fail (qtdemux != NULL, FALSE);
10259   g_return_val_if_fail (stream != NULL, FALSE);
10260   g_return_val_if_fail (container != NULL, FALSE);
10261   g_return_val_if_fail (original_fmt != NULL, FALSE);
10262
10263   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10264   if (G_UNLIKELY (!sinf)) {
10265     if (stream->protection_scheme_type == FOURCC_cenc) {
10266       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10267           "mandatory for Common Encryption");
10268       return FALSE;
10269     }
10270     return TRUE;
10271   }
10272
10273   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10274   if (G_UNLIKELY (!frma)) {
10275     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10276     return FALSE;
10277   }
10278
10279   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10280   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10281       GST_FOURCC_ARGS (*original_fmt));
10282
10283   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10284   if (!schm) {
10285     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10286     return FALSE;
10287   }
10288   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10289   stream->protection_scheme_version =
10290       QT_UINT32 ((const guint8 *) schm->data + 16);
10291
10292   GST_DEBUG_OBJECT (qtdemux,
10293       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10294       "protection_scheme_version: %#010x",
10295       GST_FOURCC_ARGS (stream->protection_scheme_type),
10296       stream->protection_scheme_version);
10297
10298   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10299   if (!schi) {
10300     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10301     return FALSE;
10302   }
10303   if (stream->protection_scheme_type != FOURCC_cenc &&
10304       stream->protection_scheme_type != FOURCC_piff) {
10305     GST_ERROR_OBJECT (qtdemux,
10306         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10307         GST_FOURCC_ARGS (stream->protection_scheme_type));
10308     return FALSE;
10309   }
10310
10311   if (G_UNLIKELY (!stream->protection_scheme_info))
10312     stream->protection_scheme_info =
10313         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10314
10315   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10316
10317   if (stream->protection_scheme_type == FOURCC_cenc) {
10318     guint32 is_encrypted;
10319     guint8 iv_size;
10320     const guint8 *default_kid;
10321
10322     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10323     if (!tenc) {
10324       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10325           "which is mandatory for Common Encryption");
10326       return FALSE;
10327     }
10328     tenc_data = (const guint8 *) tenc->data + 12;
10329     is_encrypted = QT_UINT24 (tenc_data);
10330     iv_size = QT_UINT8 (tenc_data + 3);
10331     default_kid = (tenc_data + 4);
10332     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10333         is_encrypted, iv_size, default_kid);
10334   } else if (stream->protection_scheme_type == FOURCC_piff) {
10335     GstByteReader br;
10336     static const guint8 piff_track_encryption_uuid[] = {
10337       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10338       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10339     };
10340
10341     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10342     if (!tenc) {
10343       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10344           "which is mandatory for Common Encryption");
10345       return FALSE;
10346     }
10347
10348     tenc_data = (const guint8 *) tenc->data + 8;
10349     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10350       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10351       GST_ERROR_OBJECT (qtdemux,
10352           "Unsupported track encryption box with uuid: %s", box_uuid);
10353       g_free (box_uuid);
10354       return FALSE;
10355     }
10356     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10357     gst_byte_reader_init (&br, tenc_data, 20);
10358     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10359       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10360       return FALSE;
10361     }
10362     stream->protection_scheme_type = FOURCC_cenc;
10363   }
10364
10365   return TRUE;
10366 }
10367
10368 static gint
10369 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10370     QtDemuxStream ** stream2)
10371 {
10372   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10373 }
10374
10375 static gboolean
10376 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10377     GNode * stbl)
10378 {
10379   GNode *svmi;
10380
10381   /*parse svmi header if existing */
10382   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10383   if (svmi) {
10384     guint len = QT_UINT32 ((guint8 *) svmi->data);
10385     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10386     if (!version) {
10387       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10388       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10389       guint8 frame_type, frame_layout;
10390       guint32 stereo_mono_change_count;
10391
10392       if (len < 18)
10393         return FALSE;
10394
10395       /* MPEG-A stereo video */
10396       if (qtdemux->major_brand == FOURCC_ss02)
10397         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10398
10399       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10400       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10401       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10402
10403       switch (frame_type) {
10404         case 0:
10405           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10406           break;
10407         case 1:
10408           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10409           break;
10410         case 2:
10411           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10412           break;
10413         case 3:
10414           /* mode 3 is primary/secondary view sequence, ie
10415            * left/right views in separate tracks. See section 7.2
10416            * of ISO/IEC 23000-11:2009 */
10417           /* In the future this might be supported using related
10418            * streams, like an enhancement track - if files like this
10419            * ever exist */
10420           GST_FIXME_OBJECT (qtdemux,
10421               "Implement stereo video in separate streams");
10422       }
10423
10424       if ((frame_layout & 0x1) == 0)
10425         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10426
10427       GST_LOG_OBJECT (qtdemux,
10428           "StereoVideo: composition type: %u, is_left_first: %u",
10429           frame_type, frame_layout);
10430
10431       if (stereo_mono_change_count > 1) {
10432         GST_FIXME_OBJECT (qtdemux,
10433             "Mixed-mono flags are not yet supported in qtdemux.");
10434       }
10435
10436       stream->multiview_mode = mode;
10437       stream->multiview_flags = flags;
10438     }
10439   }
10440
10441   return TRUE;
10442 }
10443
10444 /* parse the traks.
10445  * With each track we associate a new QtDemuxStream that contains all the info
10446  * about the trak.
10447  * traks that do not decode to something (like strm traks) will not have a pad.
10448  */
10449 static gboolean
10450 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10451 {
10452   GstByteReader tkhd;
10453   int offset;
10454   GNode *mdia;
10455   GNode *mdhd;
10456   GNode *hdlr;
10457   GNode *minf;
10458   GNode *stbl;
10459   GNode *stsd;
10460   GNode *mp4a;
10461   GNode *mp4v;
10462   GNode *esds;
10463   GNode *tref;
10464   GNode *udta;
10465
10466   QtDemuxStream *stream = NULL;
10467   const guint8 *stsd_data;
10468   const guint8 *stsd_entry_data;
10469   guint remaining_stsd_len;
10470   guint stsd_entry_count;
10471   guint stsd_index;
10472   guint16 lang_code;            /* quicktime lang code or packed iso code */
10473   guint32 version;
10474   guint32 tkhd_flags = 0;
10475   guint8 tkhd_version = 0;
10476   guint32 w = 0, h = 0;
10477   guint value_size, stsd_len, len;
10478   guint32 track_id;
10479   guint32 dummy;
10480
10481   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10482
10483   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10484       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10485       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10486     goto corrupt_file;
10487
10488   /* pick between 64 or 32 bits */
10489   value_size = tkhd_version == 1 ? 8 : 4;
10490   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10491       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10492     goto corrupt_file;
10493
10494   /* Check if current moov has duplicated track_id */
10495   if (qtdemux_find_stream (qtdemux, track_id))
10496     goto existing_stream;
10497
10498   stream = _create_stream (qtdemux, track_id);
10499   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10500
10501   /* need defaults for fragments */
10502   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10503
10504   if ((tkhd_flags & 1) == 0)
10505     stream->disabled = TRUE;
10506
10507   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10508       tkhd_version, tkhd_flags, stream->track_id);
10509
10510   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10511     goto corrupt_file;
10512
10513   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10514     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10515     if (qtdemux->major_brand != FOURCC_mjp2 ||
10516         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10517       goto corrupt_file;
10518   }
10519
10520   len = QT_UINT32 ((guint8 *) mdhd->data);
10521   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10522   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10523   if (version == 0x01000000) {
10524     if (len < 42)
10525       goto corrupt_file;
10526     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10527     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10528     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10529   } else {
10530     if (len < 30)
10531       goto corrupt_file;
10532     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10533     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10534     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10535   }
10536
10537   if (lang_code < 0x400) {
10538     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10539   } else if (lang_code == 0x7fff) {
10540     stream->lang_id[0] = 0;     /* unspecified */
10541   } else {
10542     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10543     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10544     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10545     stream->lang_id[3] = 0;
10546   }
10547
10548   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10549       stream->timescale);
10550   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10551       stream->duration);
10552   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10553       lang_code, stream->lang_id);
10554
10555   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10556     goto corrupt_file;
10557
10558   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10559     /* chapters track reference */
10560     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10561     if (chap) {
10562       gsize length = GST_READ_UINT32_BE (chap->data);
10563       if (qtdemux->chapters_track_id)
10564         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10565
10566       if (length >= 12) {
10567         qtdemux->chapters_track_id =
10568             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10569       }
10570     }
10571   }
10572
10573   /* fragmented files may have bogus duration in moov */
10574   if (!qtdemux->fragmented &&
10575       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10576     guint64 tdur1, tdur2;
10577
10578     /* don't overflow */
10579     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10580     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10581
10582     /* HACK:
10583      * some of those trailers, nowadays, have prologue images that are
10584      * themselves video tracks as well. I haven't really found a way to
10585      * identify those yet, except for just looking at their duration. */
10586     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10587       GST_WARNING_OBJECT (qtdemux,
10588           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10589           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10590           "found, assuming preview image or something; skipping track",
10591           stream->duration, stream->timescale, qtdemux->duration,
10592           qtdemux->timescale);
10593       gst_qtdemux_stream_unref (stream);
10594       return TRUE;
10595     }
10596   }
10597
10598   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10599     goto corrupt_file;
10600
10601   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10602       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10603
10604   len = QT_UINT32 ((guint8 *) hdlr->data);
10605   if (len >= 20)
10606     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10607   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10608       GST_FOURCC_ARGS (stream->subtype));
10609
10610   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10611     goto corrupt_file;
10612
10613   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10614     goto corrupt_file;
10615
10616   /* Parse out svmi (and later st3d/sv3d) atoms */
10617   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10618     goto corrupt_file;
10619
10620   /* parse rest of tkhd */
10621   if (stream->subtype == FOURCC_vide) {
10622     guint32 matrix[9];
10623
10624     /* version 1 uses some 64-bit ints */
10625     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10626       goto corrupt_file;
10627
10628     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10629       goto corrupt_file;
10630
10631     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10632         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10633       goto corrupt_file;
10634
10635     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10636         &stream->stream_tags);
10637   }
10638
10639   /* parse stsd */
10640   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10641     goto corrupt_file;
10642   stsd_data = (const guint8 *) stsd->data;
10643
10644   /* stsd should at least have one entry */
10645   stsd_len = QT_UINT32 (stsd_data);
10646   if (stsd_len < 24) {
10647     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10648     if (stream->subtype == FOURCC_vivo) {
10649       gst_qtdemux_stream_unref (stream);
10650       return TRUE;
10651     } else {
10652       goto corrupt_file;
10653     }
10654   }
10655
10656   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10657   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10658   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10659   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10660
10661   stsd_entry_data = stsd_data + 16;
10662   remaining_stsd_len = stsd_len - 16;
10663   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10664     guint32 fourcc;
10665     gchar *codec = NULL;
10666     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10667
10668     /* and that entry should fit within stsd */
10669     len = QT_UINT32 (stsd_entry_data);
10670     if (len > remaining_stsd_len)
10671       goto corrupt_file;
10672
10673     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10674     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10675         GST_FOURCC_ARGS (entry->fourcc));
10676     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10677
10678     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10679       goto error_encrypted;
10680
10681     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10682       /* FIXME this looks wrong, there might be multiple children
10683        * with the same type */
10684       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10685       stream->protected = TRUE;
10686       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10687         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10688     }
10689
10690     if (stream->subtype == FOURCC_vide) {
10691       GNode *colr;
10692       GNode *fiel;
10693       GNode *pasp;
10694       gboolean gray;
10695       gint depth, palette_size, palette_count;
10696       guint32 *palette_data = NULL;
10697
10698       entry->sampled = TRUE;
10699
10700       stream->display_width = w >> 16;
10701       stream->display_height = h >> 16;
10702
10703       offset = 16;
10704       if (len < 86)             /* TODO verify */
10705         goto corrupt_file;
10706
10707       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10708       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10709       entry->fps_n = 0;         /* this is filled in later */
10710       entry->fps_d = 0;         /* this is filled in later */
10711       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10712       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10713
10714       /* if color_table_id is 0, ctab atom must follow; however some files
10715        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10716        * if color table is not present we'll correct the value */
10717       if (entry->color_table_id == 0 &&
10718           (len < 90
10719               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10720         entry->color_table_id = -1;
10721       }
10722
10723       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10724           entry->width, entry->height, entry->bits_per_sample,
10725           entry->color_table_id);
10726
10727       depth = entry->bits_per_sample;
10728
10729       /* more than 32 bits means grayscale */
10730       gray = (depth > 32);
10731       /* low 32 bits specify the depth  */
10732       depth &= 0x1F;
10733
10734       /* different number of palette entries is determined by depth. */
10735       palette_count = 0;
10736       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10737         palette_count = (1 << depth);
10738       palette_size = palette_count * 4;
10739
10740       if (entry->color_table_id) {
10741         switch (palette_count) {
10742           case 0:
10743             break;
10744           case 2:
10745             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10746             break;
10747           case 4:
10748             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10749             break;
10750           case 16:
10751             if (gray)
10752               palette_data =
10753                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10754             else
10755               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10756             break;
10757           case 256:
10758             if (gray)
10759               palette_data =
10760                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10761             else
10762               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10763             break;
10764           default:
10765             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10766                 (_("The video in this file might not play correctly.")),
10767                 ("unsupported palette depth %d", depth));
10768             break;
10769         }
10770       } else {
10771         gint i, j, start, end;
10772
10773         if (len < 94)
10774           goto corrupt_file;
10775
10776         /* read table */
10777         start = QT_UINT32 (stsd_entry_data + offset + 70);
10778         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10779         end = QT_UINT16 (stsd_entry_data + offset + 76);
10780
10781         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10782             start, end, palette_count);
10783
10784         if (end > 255)
10785           end = 255;
10786         if (start > end)
10787           start = end;
10788
10789         if (len < 94 + (end - start) * 8)
10790           goto corrupt_file;
10791
10792         /* palette is always the same size */
10793         palette_data = g_malloc0 (256 * 4);
10794         palette_size = 256 * 4;
10795
10796         for (j = 0, i = start; i <= end; j++, i++) {
10797           guint32 a, r, g, b;
10798
10799           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10800           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10801           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10802           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10803
10804           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10805               (g & 0xff00) | (b >> 8);
10806         }
10807       }
10808
10809       if (entry->caps)
10810         gst_caps_unref (entry->caps);
10811
10812       entry->caps =
10813           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10814           &codec);
10815       if (G_UNLIKELY (!entry->caps)) {
10816         g_free (palette_data);
10817         goto unknown_stream;
10818       }
10819
10820       if (codec) {
10821         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10822             GST_TAG_VIDEO_CODEC, codec, NULL);
10823         g_free (codec);
10824         codec = NULL;
10825       }
10826
10827       if (palette_data) {
10828         GstStructure *s;
10829
10830         if (entry->rgb8_palette)
10831           gst_memory_unref (entry->rgb8_palette);
10832         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10833             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10834
10835         s = gst_caps_get_structure (entry->caps, 0);
10836
10837         /* non-raw video has a palette_data property. raw video has the palette as
10838          * an extra plane that we append to the output buffers before we push
10839          * them*/
10840         if (!gst_structure_has_name (s, "video/x-raw")) {
10841           GstBuffer *palette;
10842
10843           palette = gst_buffer_new ();
10844           gst_buffer_append_memory (palette, entry->rgb8_palette);
10845           entry->rgb8_palette = NULL;
10846
10847           gst_caps_set_simple (entry->caps, "palette_data",
10848               GST_TYPE_BUFFER, palette, NULL);
10849           gst_buffer_unref (palette);
10850         }
10851       } else if (palette_count != 0) {
10852         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10853             (NULL), ("Unsupported palette depth %d", depth));
10854       }
10855
10856       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10857           QT_UINT16 (stsd_entry_data + offset + 32));
10858
10859       esds = NULL;
10860       pasp = NULL;
10861       colr = NULL;
10862       fiel = NULL;
10863       /* pick 'the' stsd child */
10864       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10865       // We should skip parsing the stsd for non-protected streams if
10866       // the entry doesn't match the fourcc, since they don't change
10867       // format. However, for protected streams we can have partial
10868       // encryption, where parts of the stream are encrypted and parts
10869       // not. For both parts of such streams, we should ensure the
10870       // esds overrides are parsed for both from the stsd.
10871       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10872         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
10873           mp4v = NULL;
10874         else if (!stream->protected)
10875           mp4v = NULL;
10876       }
10877
10878       if (mp4v) {
10879         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10880         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10881         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10882         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10883       }
10884
10885       if (pasp) {
10886         const guint8 *pasp_data = (const guint8 *) pasp->data;
10887         gint len = QT_UINT32 (pasp_data);
10888
10889         if (len == 16) {
10890           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10891           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10892         } else {
10893           CUR_STREAM (stream)->par_w = 0;
10894           CUR_STREAM (stream)->par_h = 0;
10895         }
10896       } else {
10897         CUR_STREAM (stream)->par_w = 0;
10898         CUR_STREAM (stream)->par_h = 0;
10899       }
10900
10901       if (fiel) {
10902         const guint8 *fiel_data = (const guint8 *) fiel->data;
10903         gint len = QT_UINT32 (fiel_data);
10904
10905         if (len == 10) {
10906           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10907           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10908         }
10909       }
10910
10911       if (colr) {
10912         const guint8 *colr_data = (const guint8 *) colr->data;
10913         gint len = QT_UINT32 (colr_data);
10914
10915         if (len == 19 || len == 18) {
10916           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10917
10918           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10919             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10920             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10921             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10922             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10923
10924             CUR_STREAM (stream)->colorimetry.primaries =
10925                 gst_video_color_primaries_from_iso (primaries);
10926             CUR_STREAM (stream)->colorimetry.transfer =
10927                 gst_video_color_transfer_from_iso (transfer_function);
10928             CUR_STREAM (stream)->colorimetry.matrix =
10929                 gst_video_color_matrix_from_iso (matrix);
10930             CUR_STREAM (stream)->colorimetry.range =
10931                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10932                 GST_VIDEO_COLOR_RANGE_16_235;
10933           } else {
10934             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10935           }
10936         } else {
10937           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10938         }
10939       }
10940
10941       if (esds) {
10942         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10943             stream->stream_tags);
10944       } else {
10945         switch (fourcc) {
10946           case FOURCC_H264:
10947           case FOURCC_avc1:
10948           case FOURCC_avc3:
10949           {
10950             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10951             const guint8 *avc_data = stsd_entry_data + 0x56;
10952
10953             /* find avcC */
10954             while (len >= 0x8) {
10955               gint size;
10956
10957               if (QT_UINT32 (avc_data) <= len)
10958                 size = QT_UINT32 (avc_data) - 0x8;
10959               else
10960                 size = len - 0x8;
10961
10962               if (size < 1)
10963                 /* No real data, so break out */
10964                 break;
10965
10966               switch (QT_FOURCC (avc_data + 0x4)) {
10967                 case FOURCC_avcC:
10968                 {
10969                   /* parse, if found */
10970                   GstBuffer *buf;
10971
10972                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10973
10974                   /* First 4 bytes are the length of the atom, the next 4 bytes
10975                    * are the fourcc, the next 1 byte is the version, and the
10976                    * subsequent bytes are profile_tier_level structure like data. */
10977                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10978                       avc_data + 8 + 1, size - 1);
10979                   buf = gst_buffer_new_and_alloc (size);
10980                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10981                   gst_caps_set_simple (entry->caps,
10982                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10983                   gst_buffer_unref (buf);
10984
10985                   break;
10986                 }
10987                 case FOURCC_strf:
10988                 {
10989                   GstBuffer *buf;
10990
10991                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10992
10993                   /* First 4 bytes are the length of the atom, the next 4 bytes
10994                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10995                    * next 1 byte is the version, and the
10996                    * subsequent bytes are sequence parameter set like data. */
10997
10998                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10999                   if (size > 1) {
11000                     gst_codec_utils_h264_caps_set_level_and_profile
11001                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11002
11003                     buf = gst_buffer_new_and_alloc (size);
11004                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11005                     gst_caps_set_simple (entry->caps,
11006                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11007                     gst_buffer_unref (buf);
11008                   }
11009                   break;
11010                 }
11011                 case FOURCC_btrt:
11012                 {
11013                   guint avg_bitrate, max_bitrate;
11014
11015                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11016                   if (size < 12)
11017                     break;
11018
11019                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11020                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11021
11022                   if (!max_bitrate && !avg_bitrate)
11023                     break;
11024
11025                   /* Some muxers seem to swap the average and maximum bitrates
11026                    * (I'm looking at you, YouTube), so we swap for sanity. */
11027                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11028                     guint temp = avg_bitrate;
11029
11030                     avg_bitrate = max_bitrate;
11031                     max_bitrate = temp;
11032                   }
11033
11034                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11035                     gst_tag_list_add (stream->stream_tags,
11036                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11037                         max_bitrate, NULL);
11038                   }
11039                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11040                     gst_tag_list_add (stream->stream_tags,
11041                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11042                         NULL);
11043                   }
11044
11045                   break;
11046                 }
11047
11048                 default:
11049                   break;
11050               }
11051
11052               len -= size + 8;
11053               avc_data += size + 8;
11054             }
11055
11056             break;
11057           }
11058           case FOURCC_H265:
11059           case FOURCC_hvc1:
11060           case FOURCC_hev1:
11061           {
11062             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11063             const guint8 *hevc_data = stsd_entry_data + 0x56;
11064
11065             /* find hevc */
11066             while (len >= 0x8) {
11067               gint size;
11068
11069               if (QT_UINT32 (hevc_data) <= len)
11070                 size = QT_UINT32 (hevc_data) - 0x8;
11071               else
11072                 size = len - 0x8;
11073
11074               if (size < 1)
11075                 /* No real data, so break out */
11076                 break;
11077
11078               switch (QT_FOURCC (hevc_data + 0x4)) {
11079                 case FOURCC_hvcC:
11080                 {
11081                   /* parse, if found */
11082                   GstBuffer *buf;
11083
11084                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11085
11086                   /* First 4 bytes are the length of the atom, the next 4 bytes
11087                    * are the fourcc, the next 1 byte is the version, and the
11088                    * subsequent bytes are sequence parameter set like data. */
11089                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11090                       (entry->caps, hevc_data + 8 + 1, size - 1);
11091
11092                   buf = gst_buffer_new_and_alloc (size);
11093                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11094                   gst_caps_set_simple (entry->caps,
11095                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11096                   gst_buffer_unref (buf);
11097                   break;
11098                 }
11099                 default:
11100                   break;
11101               }
11102               len -= size + 8;
11103               hevc_data += size + 8;
11104             }
11105             break;
11106           }
11107           case FOURCC_mp4v:
11108           case FOURCC_MP4V:
11109           case FOURCC_fmp4:
11110           case FOURCC_FMP4:
11111           case FOURCC_xvid:
11112           case FOURCC_XVID:
11113           {
11114             GNode *glbl;
11115
11116             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11117                 GST_FOURCC_ARGS (fourcc));
11118
11119             /* codec data might be in glbl extension atom */
11120             glbl = mp4v ?
11121                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11122             if (glbl) {
11123               guint8 *data;
11124               GstBuffer *buf;
11125               gint len;
11126
11127               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11128               data = glbl->data;
11129               len = QT_UINT32 (data);
11130               if (len > 0x8) {
11131                 len -= 0x8;
11132                 buf = gst_buffer_new_and_alloc (len);
11133                 gst_buffer_fill (buf, 0, data + 8, len);
11134                 gst_caps_set_simple (entry->caps,
11135                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11136                 gst_buffer_unref (buf);
11137               }
11138             }
11139             break;
11140           }
11141           case FOURCC_mjp2:
11142           {
11143             /* see annex I of the jpeg2000 spec */
11144             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11145             const guint8 *data;
11146             const gchar *colorspace = NULL;
11147             gint ncomp = 0;
11148             guint32 ncomp_map = 0;
11149             gint32 *comp_map = NULL;
11150             guint32 nchan_def = 0;
11151             gint32 *chan_def = NULL;
11152
11153             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11154             /* some required atoms */
11155             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11156             if (!mjp2)
11157               break;
11158             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11159             if (!jp2h)
11160               break;
11161
11162             /* number of components; redundant with info in codestream, but useful
11163                to a muxer */
11164             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11165             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11166               break;
11167             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11168
11169             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11170             if (!colr)
11171               break;
11172             GST_DEBUG_OBJECT (qtdemux, "found colr");
11173             /* extract colour space info */
11174             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11175               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11176                 case 16:
11177                   colorspace = "sRGB";
11178                   break;
11179                 case 17:
11180                   colorspace = "GRAY";
11181                   break;
11182                 case 18:
11183                   colorspace = "sYUV";
11184                   break;
11185                 default:
11186                   colorspace = NULL;
11187                   break;
11188               }
11189             }
11190             if (!colorspace)
11191               /* colr is required, and only values 16, 17, and 18 are specified,
11192                  so error if we have no colorspace */
11193               break;
11194
11195             /* extract component mapping */
11196             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11197             if (cmap) {
11198               guint32 cmap_len = 0;
11199               int i;
11200               cmap_len = QT_UINT32 (cmap->data);
11201               if (cmap_len >= 8) {
11202                 /* normal box, subtract off header */
11203                 cmap_len -= 8;
11204                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11205                 if (cmap_len % 4 == 0) {
11206                   ncomp_map = (cmap_len / 4);
11207                   comp_map = g_new0 (gint32, ncomp_map);
11208                   for (i = 0; i < ncomp_map; i++) {
11209                     guint16 cmp;
11210                     guint8 mtyp, pcol;
11211                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11212                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11213                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11214                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11215                   }
11216                 }
11217               }
11218             }
11219             /* extract channel definitions */
11220             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11221             if (cdef) {
11222               guint32 cdef_len = 0;
11223               int i;
11224               cdef_len = QT_UINT32 (cdef->data);
11225               if (cdef_len >= 10) {
11226                 /* normal box, subtract off header and len */
11227                 cdef_len -= 10;
11228                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11229                 if (cdef_len % 6 == 0) {
11230                   nchan_def = (cdef_len / 6);
11231                   chan_def = g_new0 (gint32, nchan_def);
11232                   for (i = 0; i < nchan_def; i++)
11233                     chan_def[i] = -1;
11234                   for (i = 0; i < nchan_def; i++) {
11235                     guint16 cn, typ, asoc;
11236                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11237                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11238                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11239                     if (cn < nchan_def) {
11240                       switch (typ) {
11241                         case 0:
11242                           chan_def[cn] = asoc;
11243                           break;
11244                         case 1:
11245                           chan_def[cn] = 0;     /* alpha */
11246                           break;
11247                         default:
11248                           chan_def[cn] = -typ;
11249                       }
11250                     }
11251                   }
11252                 }
11253               }
11254             }
11255
11256             gst_caps_set_simple (entry->caps,
11257                 "num-components", G_TYPE_INT, ncomp, NULL);
11258             gst_caps_set_simple (entry->caps,
11259                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11260
11261             if (comp_map) {
11262               GValue arr = { 0, };
11263               GValue elt = { 0, };
11264               int i;
11265               g_value_init (&arr, GST_TYPE_ARRAY);
11266               g_value_init (&elt, G_TYPE_INT);
11267               for (i = 0; i < ncomp_map; i++) {
11268                 g_value_set_int (&elt, comp_map[i]);
11269                 gst_value_array_append_value (&arr, &elt);
11270               }
11271               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11272                   "component-map", &arr);
11273               g_value_unset (&elt);
11274               g_value_unset (&arr);
11275               g_free (comp_map);
11276             }
11277
11278             if (chan_def) {
11279               GValue arr = { 0, };
11280               GValue elt = { 0, };
11281               int i;
11282               g_value_init (&arr, GST_TYPE_ARRAY);
11283               g_value_init (&elt, G_TYPE_INT);
11284               for (i = 0; i < nchan_def; i++) {
11285                 g_value_set_int (&elt, chan_def[i]);
11286                 gst_value_array_append_value (&arr, &elt);
11287               }
11288               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11289                   "channel-definitions", &arr);
11290               g_value_unset (&elt);
11291               g_value_unset (&arr);
11292               g_free (chan_def);
11293             }
11294
11295             /* some optional atoms */
11296             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11297             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11298
11299             /* indicate possible fields in caps */
11300             if (field) {
11301               data = (guint8 *) field->data + 8;
11302               if (*data != 1)
11303                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11304                     (gint) * data, NULL);
11305             }
11306             /* add codec_data if provided */
11307             if (prefix) {
11308               GstBuffer *buf;
11309               gint len;
11310
11311               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11312               data = prefix->data;
11313               len = QT_UINT32 (data);
11314               if (len > 0x8) {
11315                 len -= 0x8;
11316                 buf = gst_buffer_new_and_alloc (len);
11317                 gst_buffer_fill (buf, 0, data + 8, len);
11318                 gst_caps_set_simple (entry->caps,
11319                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11320                 gst_buffer_unref (buf);
11321               }
11322             }
11323             break;
11324           }
11325           case FOURCC_SVQ3:
11326           case FOURCC_VP31:
11327           {
11328             GstBuffer *buf;
11329             GstBuffer *seqh = NULL;
11330             const guint8 *gamma_data = NULL;
11331             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11332
11333             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11334                 &seqh);
11335             if (gamma_data) {
11336               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11337                   QT_FP32 (gamma_data), NULL);
11338             }
11339             if (seqh) {
11340               /* sorry for the bad name, but we don't know what this is, other
11341                * than its own fourcc */
11342               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11343                   NULL);
11344               gst_buffer_unref (seqh);
11345             }
11346
11347             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11348             buf = gst_buffer_new_and_alloc (len);
11349             gst_buffer_fill (buf, 0, stsd_data, len);
11350             gst_caps_set_simple (entry->caps,
11351                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11352             gst_buffer_unref (buf);
11353             break;
11354           }
11355           case FOURCC_jpeg:
11356           {
11357             /* https://developer.apple.com/standards/qtff-2001.pdf,
11358              * page 92, "Video Sample Description", under table 3.1 */
11359             GstByteReader br;
11360
11361             const gint compressor_offset =
11362                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11363             const gint min_size = compressor_offset + 32 + 2 + 2;
11364             GNode *jpeg;
11365             guint32 len;
11366             guint16 color_table_id = 0;
11367             gboolean ok;
11368
11369             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11370
11371             /* recover information on interlaced/progressive */
11372             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11373             if (!jpeg)
11374               break;
11375
11376             len = QT_UINT32 (jpeg->data);
11377             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11378                 min_size);
11379             if (len >= min_size) {
11380               gst_byte_reader_init (&br, jpeg->data, len);
11381
11382               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11383               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11384               if (color_table_id != 0) {
11385                 /* the spec says there can be concatenated chunks in the data, and we want
11386                  * to find one called field. Walk through them. */
11387                 gint offset = min_size;
11388                 while (offset + 8 < len) {
11389                   guint32 size = 0, tag;
11390                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11391                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11392                   if (!ok || size < 8) {
11393                     GST_WARNING_OBJECT (qtdemux,
11394                         "Failed to walk optional chunk list");
11395                     break;
11396                   }
11397                   GST_DEBUG_OBJECT (qtdemux,
11398                       "Found optional %4.4s chunk, size %u",
11399                       (const char *) &tag, size);
11400                   if (tag == FOURCC_fiel) {
11401                     guint8 n_fields = 0, ordering = 0;
11402                     gst_byte_reader_get_uint8 (&br, &n_fields);
11403                     gst_byte_reader_get_uint8 (&br, &ordering);
11404                     if (n_fields == 1 || n_fields == 2) {
11405                       GST_DEBUG_OBJECT (qtdemux,
11406                           "Found fiel tag with %u fields, ordering %u",
11407                           n_fields, ordering);
11408                       if (n_fields == 2)
11409                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11410                             "interlace-mode", G_TYPE_STRING, "interleaved",
11411                             NULL);
11412                     } else {
11413                       GST_WARNING_OBJECT (qtdemux,
11414                           "Found fiel tag with invalid fields (%u)", n_fields);
11415                     }
11416                   }
11417                   offset += size;
11418                 }
11419               } else {
11420                 GST_DEBUG_OBJECT (qtdemux,
11421                     "Color table ID is 0, not trying to get interlacedness");
11422               }
11423             } else {
11424               GST_WARNING_OBJECT (qtdemux,
11425                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11426             }
11427
11428             break;
11429           }
11430           case FOURCC_rle_:
11431           case FOURCC_WRLE:
11432           {
11433             gst_caps_set_simple (entry->caps,
11434                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11435                 NULL);
11436             break;
11437           }
11438           case FOURCC_XiTh:
11439           {
11440             GNode *xith, *xdxt;
11441
11442             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11443             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11444             if (!xith)
11445               break;
11446
11447             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11448             if (!xdxt)
11449               break;
11450
11451             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11452             /* collect the headers and store them in a stream list so that we can
11453              * send them out first */
11454             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11455             break;
11456           }
11457           case FOURCC_ovc1:
11458           {
11459             GNode *ovc1;
11460             guint8 *ovc1_data;
11461             guint ovc1_len;
11462             GstBuffer *buf;
11463
11464             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11465             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11466             if (!ovc1)
11467               break;
11468             ovc1_data = ovc1->data;
11469             ovc1_len = QT_UINT32 (ovc1_data);
11470             if (ovc1_len <= 198) {
11471               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11472               break;
11473             }
11474             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11475             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11476             gst_caps_set_simple (entry->caps,
11477                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11478             gst_buffer_unref (buf);
11479             break;
11480           }
11481           case FOURCC_vc_1:
11482           {
11483             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11484             const guint8 *vc1_data = stsd_entry_data + 0x56;
11485
11486             /* find dvc1 */
11487             while (len >= 8) {
11488               gint size;
11489
11490               if (QT_UINT32 (vc1_data) <= len)
11491                 size = QT_UINT32 (vc1_data) - 8;
11492               else
11493                 size = len - 8;
11494
11495               if (size < 1)
11496                 /* No real data, so break out */
11497                 break;
11498
11499               switch (QT_FOURCC (vc1_data + 0x4)) {
11500                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11501                 {
11502                   GstBuffer *buf;
11503
11504                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11505                   buf = gst_buffer_new_and_alloc (size);
11506                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11507                   gst_caps_set_simple (entry->caps,
11508                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11509                   gst_buffer_unref (buf);
11510                   break;
11511                 }
11512                 default:
11513                   break;
11514               }
11515               len -= size + 8;
11516               vc1_data += size + 8;
11517             }
11518             break;
11519           }
11520           case FOURCC_av01:
11521           {
11522             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11523             const guint8 *av1_data = stsd_entry_data + 0x56;
11524
11525             /* find av1C */
11526             while (len >= 0x8) {
11527               gint size;
11528
11529               if (QT_UINT32 (av1_data) <= len)
11530                 size = QT_UINT32 (av1_data) - 0x8;
11531               else
11532                 size = len - 0x8;
11533
11534               if (size < 1)
11535                 /* No real data, so break out */
11536                 break;
11537
11538               switch (QT_FOURCC (av1_data + 0x4)) {
11539                 case FOURCC_av1C:
11540                 {
11541                   /* parse, if found */
11542                   GstBuffer *buf;
11543                   guint8 pres_delay_field;
11544
11545                   GST_DEBUG_OBJECT (qtdemux,
11546                       "found av1C codec_data in stsd of size %d", size);
11547
11548                   /* not enough data, just ignore and hope for the best */
11549                   if (size < 5)
11550                     break;
11551
11552                   /* Content is:
11553                    * 4 bytes: atom length
11554                    * 4 bytes: fourcc
11555                    * 1 byte: version
11556                    * 3 bytes: flags
11557                    * 3 bits: reserved
11558                    * 1 bits:  initial_presentation_delay_present
11559                    * 4 bits: initial_presentation_delay (if present else reserved
11560                    * rest: OBUs.
11561                    */
11562
11563                   if (av1_data[9] != 0) {
11564                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11565                     break;
11566                   }
11567
11568                   /* We skip initial_presentation_delay* for now */
11569                   pres_delay_field = *(av1_data + 12);
11570                   if (pres_delay_field & (1 << 5)) {
11571                     gst_caps_set_simple (entry->caps,
11572                         "presentation-delay", G_TYPE_INT,
11573                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11574                   }
11575                   if (size > 5) {
11576                     buf = gst_buffer_new_and_alloc (size - 5);
11577                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11578                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11579                     gst_caps_set_simple (entry->caps,
11580                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11581                     gst_buffer_unref (buf);
11582                   }
11583                   break;
11584                 }
11585                 default:
11586                   break;
11587               }
11588
11589               len -= size + 8;
11590               av1_data += size + 8;
11591             }
11592
11593             break;
11594           }
11595
11596             /* TODO: Need to parse vpcC for VP8 codec too.
11597              * Note that VPCodecConfigurationBox (vpcC) is defined for
11598              * vp08, vp09, and vp10 fourcc. */
11599           case FOURCC_vp09:
11600           {
11601             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11602             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11603
11604             /* find vpcC */
11605             while (len >= 0x8) {
11606               gint size;
11607
11608               if (QT_UINT32 (vpcc_data) <= len)
11609                 size = QT_UINT32 (vpcc_data) - 0x8;
11610               else
11611                 size = len - 0x8;
11612
11613               if (size < 1)
11614                 /* No real data, so break out */
11615                 break;
11616
11617               switch (QT_FOURCC (vpcc_data + 0x4)) {
11618                 case FOURCC_vpcC:
11619                 {
11620                   const gchar *profile_str = NULL;
11621                   const gchar *chroma_format_str = NULL;
11622                   guint8 profile;
11623                   guint8 bitdepth;
11624                   guint8 chroma_format;
11625                   GstVideoColorimetry cinfo;
11626
11627                   /* parse, if found */
11628                   GST_DEBUG_OBJECT (qtdemux,
11629                       "found vp codec_data in stsd of size %d", size);
11630
11631                   /* the meaning of "size" is length of the atom body, excluding
11632                    * atom length and fourcc fields */
11633                   if (size < 12)
11634                     break;
11635
11636                   /* Content is:
11637                    * 4 bytes: atom length
11638                    * 4 bytes: fourcc
11639                    * 1 byte: version
11640                    * 3 bytes: flags
11641                    * 1 byte: profile
11642                    * 1 byte: level
11643                    * 4 bits: bitDepth
11644                    * 3 bits: chromaSubsampling
11645                    * 1 bit: videoFullRangeFlag
11646                    * 1 byte: colourPrimaries
11647                    * 1 byte: transferCharacteristics
11648                    * 1 byte: matrixCoefficients
11649                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11650                    * rest: codecIntializationData (not used for vp8 and vp9)
11651                    */
11652
11653                   if (vpcc_data[8] != 1) {
11654                     GST_WARNING_OBJECT (qtdemux,
11655                         "unknown vpcC version %d", vpcc_data[8]);
11656                     break;
11657                   }
11658
11659                   profile = vpcc_data[12];
11660                   switch (profile) {
11661                     case 0:
11662                       profile_str = "0";
11663                       break;
11664                     case 1:
11665                       profile_str = "1";
11666                       break;
11667                     case 2:
11668                       profile_str = "2";
11669                       break;
11670                     case 3:
11671                       profile_str = "3";
11672                       break;
11673                     default:
11674                       break;
11675                   }
11676
11677                   if (profile_str) {
11678                     gst_caps_set_simple (entry->caps,
11679                         "profile", G_TYPE_STRING, profile_str, NULL);
11680                   }
11681
11682                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11683                    * but webm spec define various ones. Add level to caps
11684                    * if we really need it then */
11685
11686                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11687                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11688                     gst_caps_set_simple (entry->caps,
11689                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11690                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11691                   }
11692
11693                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
11694                   switch (chroma_format) {
11695                     case 0:
11696                     case 1:
11697                       chroma_format_str = "4:2:0";
11698                       break;
11699                     case 2:
11700                       chroma_format_str = "4:2:2";
11701                       break;
11702                     case 3:
11703                       chroma_format_str = "4:4:4";
11704                       break;
11705                     default:
11706                       break;
11707                   }
11708
11709                   if (chroma_format_str) {
11710                     gst_caps_set_simple (entry->caps,
11711                         "chroma-format", G_TYPE_STRING, chroma_format_str,
11712                         NULL);
11713                   }
11714
11715                   if ((vpcc_data[14] & 0x1) != 0)
11716                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
11717                   else
11718                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
11719                   cinfo.primaries =
11720                       gst_video_color_primaries_from_iso (vpcc_data[15]);
11721                   cinfo.transfer =
11722                       gst_video_color_transfer_from_iso (vpcc_data[16]);
11723                   cinfo.matrix =
11724                       gst_video_color_matrix_from_iso (vpcc_data[17]);
11725
11726                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
11727                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
11728                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
11729                     /* set this only if all values are known, otherwise this
11730                      * might overwrite valid ones parsed from other color box */
11731                     CUR_STREAM (stream)->colorimetry = cinfo;
11732                   }
11733                   break;
11734                 }
11735                 default:
11736                   break;
11737               }
11738
11739               len -= size + 8;
11740               vpcc_data += size + 8;
11741             }
11742
11743             break;
11744           }
11745           default:
11746             break;
11747         }
11748       }
11749
11750       GST_INFO_OBJECT (qtdemux,
11751           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11752           GST_FOURCC_ARGS (fourcc), entry->caps);
11753
11754     } else if (stream->subtype == FOURCC_soun) {
11755       GNode *wave;
11756       int version, samplesize;
11757       guint16 compression_id;
11758       gboolean amrwb = FALSE;
11759
11760       offset = 16;
11761       /* sample description entry (16) + sound sample description v0 (20) */
11762       if (len < 36)
11763         goto corrupt_file;
11764
11765       version = QT_UINT32 (stsd_entry_data + offset);
11766       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11767       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11768       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11769       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11770
11771       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11772       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11773           QT_UINT32 (stsd_entry_data + offset + 4));
11774       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11775       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11776       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11777       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11778           QT_UINT16 (stsd_entry_data + offset + 14));
11779       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11780
11781       if (compression_id == 0xfffe)
11782         entry->sampled = TRUE;
11783
11784       /* first assume uncompressed audio */
11785       entry->bytes_per_sample = samplesize / 8;
11786       entry->samples_per_frame = entry->n_channels;
11787       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11788       entry->samples_per_packet = entry->samples_per_frame;
11789       entry->bytes_per_packet = entry->bytes_per_sample;
11790
11791       offset = 36;
11792
11793       if (version == 0x00010000) {
11794         /* sample description entry (16) + sound sample description v1 (20+16) */
11795         if (len < 52)
11796           goto corrupt_file;
11797
11798         /* take information from here over the normal sample description */
11799         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11800         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11801         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11802         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11803
11804         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
11805         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11806             entry->samples_per_packet);
11807         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11808             entry->bytes_per_packet);
11809         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11810             entry->bytes_per_frame);
11811         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11812             entry->bytes_per_sample);
11813
11814         if (!entry->sampled && entry->bytes_per_packet) {
11815           entry->samples_per_frame = (entry->bytes_per_frame /
11816               entry->bytes_per_packet) * entry->samples_per_packet;
11817           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11818               entry->samples_per_frame);
11819         }
11820       } else if (version == 0x00020000) {
11821         /* sample description entry (16) + sound sample description v2 (56) */
11822         if (len < 72)
11823           goto corrupt_file;
11824
11825         /* take information from here over the normal sample description */
11826         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
11827         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11828         entry->samples_per_frame = entry->n_channels;
11829         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
11830         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
11831         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
11832         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
11833
11834         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11835         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11836         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11837         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11838             entry->bytes_per_sample * 8);
11839         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11840             QT_UINT32 (stsd_entry_data + offset + 24));
11841         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11842             entry->bytes_per_packet);
11843         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11844             entry->samples_per_packet);
11845       } else if (version != 0x00000) {
11846         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11847             version);
11848       }
11849
11850       switch (fourcc) {
11851           /* Yes, these have to be hard-coded */
11852         case FOURCC_MAC6:
11853         {
11854           entry->samples_per_packet = 6;
11855           entry->bytes_per_packet = 1;
11856           entry->bytes_per_frame = 1 * entry->n_channels;
11857           entry->bytes_per_sample = 1;
11858           entry->samples_per_frame = 6 * entry->n_channels;
11859           break;
11860         }
11861         case FOURCC_MAC3:
11862         {
11863           entry->samples_per_packet = 3;
11864           entry->bytes_per_packet = 1;
11865           entry->bytes_per_frame = 1 * entry->n_channels;
11866           entry->bytes_per_sample = 1;
11867           entry->samples_per_frame = 3 * entry->n_channels;
11868           break;
11869         }
11870         case FOURCC_ima4:
11871         {
11872           entry->samples_per_packet = 64;
11873           entry->bytes_per_packet = 34;
11874           entry->bytes_per_frame = 34 * entry->n_channels;
11875           entry->bytes_per_sample = 2;
11876           entry->samples_per_frame = 64 * entry->n_channels;
11877           break;
11878         }
11879         case FOURCC_ulaw:
11880         case FOURCC_alaw:
11881         {
11882           entry->samples_per_packet = 1;
11883           entry->bytes_per_packet = 1;
11884           entry->bytes_per_frame = 1 * entry->n_channels;
11885           entry->bytes_per_sample = 1;
11886           entry->samples_per_frame = 1 * entry->n_channels;
11887           break;
11888         }
11889         case FOURCC_agsm:
11890         {
11891           entry->samples_per_packet = 160;
11892           entry->bytes_per_packet = 33;
11893           entry->bytes_per_frame = 33 * entry->n_channels;
11894           entry->bytes_per_sample = 2;
11895           entry->samples_per_frame = 160 * entry->n_channels;
11896           break;
11897         }
11898           /* fix up any invalid header information from above */
11899         case FOURCC_twos:
11900         case FOURCC_sowt:
11901         case FOURCC_raw_:
11902         case FOURCC_lpcm:
11903           /* Sometimes these are set to 0 in the sound sample descriptions so
11904            * let's try to infer useful values from the other information we
11905            * have available */
11906           if (entry->bytes_per_sample == 0)
11907             entry->bytes_per_sample =
11908                 entry->bytes_per_frame / entry->n_channels;
11909           if (entry->bytes_per_sample == 0)
11910             entry->bytes_per_sample = samplesize / 8;
11911
11912           if (entry->bytes_per_frame == 0)
11913             entry->bytes_per_frame =
11914                 entry->bytes_per_sample * entry->n_channels;
11915
11916           if (entry->bytes_per_packet == 0)
11917             entry->bytes_per_packet = entry->bytes_per_sample;
11918
11919           if (entry->samples_per_frame == 0)
11920             entry->samples_per_frame = entry->n_channels;
11921
11922           if (entry->samples_per_packet == 0)
11923             entry->samples_per_packet = entry->samples_per_frame;
11924
11925           break;
11926         case FOURCC_in24:
11927         case FOURCC_in32:
11928         case FOURCC_fl32:
11929         case FOURCC_fl64:
11930         case FOURCC_s16l:{
11931           switch (fourcc) {
11932             case FOURCC_in24:
11933               entry->bytes_per_sample = 3;
11934               break;
11935             case FOURCC_in32:
11936             case FOURCC_fl32:
11937               entry->bytes_per_sample = 4;
11938               break;
11939             case FOURCC_fl64:
11940               entry->bytes_per_sample = 8;
11941               break;
11942             case FOURCC_s16l:
11943               entry->bytes_per_sample = 2;
11944               break;
11945             default:
11946               g_assert_not_reached ();
11947               break;
11948           }
11949           entry->samples_per_frame = entry->n_channels;
11950           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11951           entry->samples_per_packet = entry->samples_per_frame;
11952           entry->bytes_per_packet = entry->bytes_per_sample;
11953           break;
11954         }
11955         default:
11956           break;
11957       }
11958
11959       if (entry->caps)
11960         gst_caps_unref (entry->caps);
11961
11962       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11963           stsd_entry_data + 32, len - 16, &codec);
11964
11965       switch (fourcc) {
11966         case FOURCC_in24:
11967         case FOURCC_in32:
11968         case FOURCC_fl32:
11969         case FOURCC_fl64:
11970         {
11971           GNode *enda;
11972           GNode *fmt;
11973
11974           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
11975
11976           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
11977           if (!enda) {
11978             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
11979             if (wave)
11980               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11981           }
11982           if (enda) {
11983             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11984             const gchar *format_str;
11985
11986             switch (fourcc) {
11987               case FOURCC_in24:
11988                 format_str = (enda_value) ? "S24LE" : "S24BE";
11989                 break;
11990               case FOURCC_in32:
11991                 format_str = (enda_value) ? "S32LE" : "S32BE";
11992                 break;
11993               case FOURCC_fl32:
11994                 format_str = (enda_value) ? "F32LE" : "F32BE";
11995                 break;
11996               case FOURCC_fl64:
11997                 format_str = (enda_value) ? "F64LE" : "F64BE";
11998                 break;
11999               default:
12000                 g_assert_not_reached ();
12001                 break;
12002             }
12003             gst_caps_set_simple (entry->caps,
12004                 "format", G_TYPE_STRING, format_str, NULL);
12005           }
12006           break;
12007         }
12008         case FOURCC_owma:
12009         {
12010           const guint8 *owma_data;
12011           const gchar *codec_name = NULL;
12012           guint owma_len;
12013           GstBuffer *buf;
12014           gint version = 1;
12015           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12016           /* FIXME this should also be gst_riff_strf_auds,
12017            * but the latter one is actually missing bits-per-sample :( */
12018           typedef struct
12019           {
12020             gint16 wFormatTag;
12021             gint16 nChannels;
12022             gint32 nSamplesPerSec;
12023             gint32 nAvgBytesPerSec;
12024             gint16 nBlockAlign;
12025             gint16 wBitsPerSample;
12026             gint16 cbSize;
12027           } WAVEFORMATEX;
12028           WAVEFORMATEX *wfex;
12029
12030           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12031           owma_data = stsd_entry_data;
12032           owma_len = QT_UINT32 (owma_data);
12033           if (owma_len <= 54) {
12034             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12035             break;
12036           }
12037           wfex = (WAVEFORMATEX *) (owma_data + 36);
12038           buf = gst_buffer_new_and_alloc (owma_len - 54);
12039           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12040           if (wfex->wFormatTag == 0x0161) {
12041             codec_name = "Windows Media Audio";
12042             version = 2;
12043           } else if (wfex->wFormatTag == 0x0162) {
12044             codec_name = "Windows Media Audio 9 Pro";
12045             version = 3;
12046           } else if (wfex->wFormatTag == 0x0163) {
12047             codec_name = "Windows Media Audio 9 Lossless";
12048             /* is that correct? gstffmpegcodecmap.c is missing it, but
12049              * fluendo codec seems to support it */
12050             version = 4;
12051           }
12052
12053           gst_caps_set_simple (entry->caps,
12054               "codec_data", GST_TYPE_BUFFER, buf,
12055               "wmaversion", G_TYPE_INT, version,
12056               "block_align", G_TYPE_INT,
12057               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12058               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12059               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12060               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12061           gst_buffer_unref (buf);
12062
12063           if (codec_name) {
12064             g_free (codec);
12065             codec = g_strdup (codec_name);
12066           }
12067           break;
12068         }
12069         case FOURCC_wma_:
12070         {
12071           gint len = QT_UINT32 (stsd_entry_data) - offset;
12072           const guint8 *wfex_data = stsd_entry_data + offset;
12073           const gchar *codec_name = NULL;
12074           gint version = 1;
12075           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12076           /* FIXME this should also be gst_riff_strf_auds,
12077            * but the latter one is actually missing bits-per-sample :( */
12078           typedef struct
12079           {
12080             gint16 wFormatTag;
12081             gint16 nChannels;
12082             gint32 nSamplesPerSec;
12083             gint32 nAvgBytesPerSec;
12084             gint16 nBlockAlign;
12085             gint16 wBitsPerSample;
12086             gint16 cbSize;
12087           } WAVEFORMATEX;
12088           WAVEFORMATEX wfex;
12089
12090           /* FIXME: unify with similar wavformatex parsing code above */
12091           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12092
12093           /* find wfex */
12094           while (len >= 8) {
12095             gint size;
12096
12097             if (QT_UINT32 (wfex_data) <= len)
12098               size = QT_UINT32 (wfex_data) - 8;
12099             else
12100               size = len - 8;
12101
12102             if (size < 1)
12103               /* No real data, so break out */
12104               break;
12105
12106             switch (QT_FOURCC (wfex_data + 4)) {
12107               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12108               {
12109                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12110
12111                 if (size < 8 + 18)
12112                   break;
12113
12114                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12115                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12116                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12117                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12118                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12119                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12120                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12121
12122                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12123                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12124                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12125                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12126                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12127                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12128
12129                 if (wfex.wFormatTag == 0x0161) {
12130                   codec_name = "Windows Media Audio";
12131                   version = 2;
12132                 } else if (wfex.wFormatTag == 0x0162) {
12133                   codec_name = "Windows Media Audio 9 Pro";
12134                   version = 3;
12135                 } else if (wfex.wFormatTag == 0x0163) {
12136                   codec_name = "Windows Media Audio 9 Lossless";
12137                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12138                    * fluendo codec seems to support it */
12139                   version = 4;
12140                 }
12141
12142                 gst_caps_set_simple (entry->caps,
12143                     "wmaversion", G_TYPE_INT, version,
12144                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12145                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12146                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12147                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12148
12149                 if (size > wfex.cbSize) {
12150                   GstBuffer *buf;
12151
12152                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12153                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12154                       size - wfex.cbSize);
12155                   gst_caps_set_simple (entry->caps,
12156                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12157                   gst_buffer_unref (buf);
12158                 } else {
12159                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12160                 }
12161
12162                 if (codec_name) {
12163                   g_free (codec);
12164                   codec = g_strdup (codec_name);
12165                 }
12166                 break;
12167               }
12168               default:
12169                 break;
12170             }
12171             len -= size + 8;
12172             wfex_data += size + 8;
12173           }
12174           break;
12175         }
12176         case FOURCC_opus:
12177         {
12178           const guint8 *opus_data;
12179           guint8 *channel_mapping = NULL;
12180           guint32 rate;
12181           guint8 channels;
12182           guint8 channel_mapping_family;
12183           guint8 stream_count;
12184           guint8 coupled_count;
12185           guint8 i;
12186
12187           opus_data = stsd_entry_data;
12188
12189           channels = GST_READ_UINT8 (opus_data + 45);
12190           rate = GST_READ_UINT32_LE (opus_data + 48);
12191           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12192           stream_count = GST_READ_UINT8 (opus_data + 55);
12193           coupled_count = GST_READ_UINT8 (opus_data + 56);
12194
12195           if (channels > 0) {
12196             channel_mapping = g_malloc (channels * sizeof (guint8));
12197             for (i = 0; i < channels; i++)
12198               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12199           }
12200
12201           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12202               channel_mapping_family, stream_count, coupled_count,
12203               channel_mapping);
12204           break;
12205         }
12206         default:
12207           break;
12208       }
12209
12210       if (codec) {
12211         GstStructure *s;
12212         gint bitrate = 0;
12213
12214         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12215             GST_TAG_AUDIO_CODEC, codec, NULL);
12216         g_free (codec);
12217         codec = NULL;
12218
12219         /* some bitrate info may have ended up in caps */
12220         s = gst_caps_get_structure (entry->caps, 0);
12221         gst_structure_get_int (s, "bitrate", &bitrate);
12222         if (bitrate > 0)
12223           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12224               GST_TAG_BITRATE, bitrate, NULL);
12225       }
12226
12227       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12228       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12229         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca)
12230           mp4a = NULL;
12231         else if (!stream->protected)
12232           mp4a = NULL;
12233       }
12234
12235       wave = NULL;
12236       esds = NULL;
12237       if (mp4a) {
12238         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12239         if (wave)
12240           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12241         if (!esds)
12242           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12243       }
12244
12245
12246       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12247          16 bits is a byte-swapped wave-style codec identifier,
12248          and we can find a WAVE header internally to a 'wave' atom here.
12249          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12250          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12251          is big-endian).
12252        */
12253       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12254         if (len < offset + 20) {
12255           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12256         } else {
12257           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12258           const guint8 *data = stsd_entry_data + offset + 16;
12259           GNode *wavenode;
12260           GNode *waveheadernode;
12261
12262           wavenode = g_node_new ((guint8 *) data);
12263           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12264             const guint8 *waveheader;
12265             guint32 headerlen;
12266
12267             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12268             if (waveheadernode) {
12269               waveheader = (const guint8 *) waveheadernode->data;
12270               headerlen = QT_UINT32 (waveheader);
12271
12272               if (headerlen > 8) {
12273                 gst_riff_strf_auds *header = NULL;
12274                 GstBuffer *headerbuf;
12275                 GstBuffer *extra;
12276
12277                 waveheader += 8;
12278                 headerlen -= 8;
12279
12280                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12281                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12282
12283                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12284                         headerbuf, &header, &extra)) {
12285                   gst_caps_unref (entry->caps);
12286                   /* FIXME: Need to do something with the channel reorder map */
12287                   entry->caps =
12288                       gst_riff_create_audio_caps (header->format, NULL, header,
12289                       extra, NULL, NULL, NULL);
12290
12291                   if (extra)
12292                     gst_buffer_unref (extra);
12293                   g_free (header);
12294                 }
12295               }
12296             } else
12297               GST_DEBUG ("Didn't find waveheadernode for this codec");
12298           }
12299           g_node_destroy (wavenode);
12300         }
12301       } else if (esds) {
12302         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12303             stream->stream_tags);
12304       } else {
12305         switch (fourcc) {
12306 #if 0
12307             /* FIXME: what is in the chunk? */
12308           case FOURCC_QDMC:
12309           {
12310             gint len = QT_UINT32 (stsd_data);
12311
12312             /* seems to be always = 116 = 0x74 */
12313             break;
12314           }
12315 #endif
12316           case FOURCC_QDM2:
12317           {
12318             gint len = QT_UINT32 (stsd_entry_data);
12319
12320             if (len > 0x3C) {
12321               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12322
12323               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12324               gst_caps_set_simple (entry->caps,
12325                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12326               gst_buffer_unref (buf);
12327             }
12328             gst_caps_set_simple (entry->caps,
12329                 "samplesize", G_TYPE_INT, samplesize, NULL);
12330             break;
12331           }
12332           case FOURCC_alac:
12333           {
12334             GNode *alac, *wave = NULL;
12335
12336             /* apparently, m4a has this atom appended directly in the stsd entry,
12337              * while mov has it in a wave atom */
12338             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12339             if (alac) {
12340               /* alac now refers to stsd entry atom */
12341               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12342               if (wave)
12343                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12344               else
12345                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12346             }
12347             if (alac) {
12348               const guint8 *alac_data = alac->data;
12349               gint len = QT_UINT32 (alac->data);
12350               GstBuffer *buf;
12351
12352               if (len < 36) {
12353                 GST_DEBUG_OBJECT (qtdemux,
12354                     "discarding alac atom with unexpected len %d", len);
12355               } else {
12356                 /* codec-data contains alac atom size and prefix,
12357                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12358                 buf = gst_buffer_new_and_alloc (len);
12359                 gst_buffer_fill (buf, 0, alac->data, len);
12360                 gst_caps_set_simple (entry->caps,
12361                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12362                 gst_buffer_unref (buf);
12363
12364                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12365                 entry->n_channels = QT_UINT8 (alac_data + 21);
12366                 entry->rate = QT_UINT32 (alac_data + 32);
12367               }
12368             }
12369             gst_caps_set_simple (entry->caps,
12370                 "samplesize", G_TYPE_INT, samplesize, NULL);
12371             break;
12372           }
12373           case FOURCC_fLaC:
12374           {
12375             /* The codingname of the sample entry is 'fLaC' */
12376             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12377
12378             if (flac) {
12379               /* The 'dfLa' box is added to the sample entry to convey
12380                  initializing information for the decoder. */
12381               const GNode *dfla =
12382                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12383
12384               if (dfla) {
12385                 const guint32 len = QT_UINT32 (dfla->data);
12386
12387                 /* Must contain at least dfLa box header (12),
12388                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12389                 if (len < 50) {
12390                   GST_DEBUG_OBJECT (qtdemux,
12391                       "discarding dfla atom with unexpected len %d", len);
12392                 } else {
12393                   /* skip dfLa header to get the METADATA_BLOCKs */
12394                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12395                   const guint32 metadata_blocks_len = len - 12;
12396
12397                   gchar *stream_marker = g_strdup ("fLaC");
12398                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12399                       strlen (stream_marker));
12400
12401                   guint32 index = 0;
12402                   guint32 remainder = 0;
12403                   guint32 block_size = 0;
12404                   gboolean is_last = FALSE;
12405
12406                   GValue array = G_VALUE_INIT;
12407                   GValue value = G_VALUE_INIT;
12408
12409                   g_value_init (&array, GST_TYPE_ARRAY);
12410                   g_value_init (&value, GST_TYPE_BUFFER);
12411
12412                   gst_value_set_buffer (&value, block);
12413                   gst_value_array_append_value (&array, &value);
12414                   g_value_reset (&value);
12415
12416                   gst_buffer_unref (block);
12417
12418                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12419                    * of data, and we haven't already finished parsing */
12420                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12421                     remainder = metadata_blocks_len - index;
12422
12423                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12424                     block_size = 4 +
12425                         (metadata_blocks[index + 1] << 16) +
12426                         (metadata_blocks[index + 2] << 8) +
12427                         metadata_blocks[index + 3];
12428
12429                     /* be careful not to read off end of box */
12430                     if (block_size > remainder) {
12431                       break;
12432                     }
12433
12434                     is_last = metadata_blocks[index] >> 7;
12435
12436                     block = gst_buffer_new_and_alloc (block_size);
12437
12438                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12439                         block_size);
12440
12441                     gst_value_set_buffer (&value, block);
12442                     gst_value_array_append_value (&array, &value);
12443                     g_value_reset (&value);
12444
12445                     gst_buffer_unref (block);
12446
12447                     index += block_size;
12448                   }
12449
12450                   /* only append the metadata if we successfully read all of it */
12451                   if (is_last) {
12452                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12453                             (stream)->caps, 0), "streamheader", &array);
12454                   } else {
12455                     GST_WARNING_OBJECT (qtdemux,
12456                         "discarding all METADATA_BLOCKs due to invalid "
12457                         "block_size %d at idx %d, rem %d", block_size, index,
12458                         remainder);
12459                   }
12460
12461                   g_value_unset (&value);
12462                   g_value_unset (&array);
12463
12464                   /* The sample rate obtained from the stsd may not be accurate
12465                    * since it cannot represent rates greater than 65535Hz, so
12466                    * override that value with the sample rate from the
12467                    * METADATA_BLOCK_STREAMINFO block */
12468                   CUR_STREAM (stream)->rate =
12469                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12470                 }
12471               }
12472             }
12473             break;
12474           }
12475           case FOURCC_sawb:
12476             /* Fallthrough! */
12477             amrwb = TRUE;
12478           case FOURCC_samr:
12479           {
12480             gint len = QT_UINT32 (stsd_entry_data);
12481
12482             if (len > 0x24) {
12483               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12484               guint bitrate;
12485
12486               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12487
12488               /* If we have enough data, let's try to get the 'damr' atom. See
12489                * the 3GPP container spec (26.244) for more details. */
12490               if ((len - 0x34) > 8 &&
12491                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12492                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12493                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12494               }
12495
12496               gst_caps_set_simple (entry->caps,
12497                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12498               gst_buffer_unref (buf);
12499             }
12500             break;
12501           }
12502           case FOURCC_mp4a:
12503           {
12504             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12505             gint len = QT_UINT32 (stsd_entry_data);
12506
12507             if (len >= 34) {
12508               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12509
12510               if (sound_version == 1) {
12511                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12512                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12513                 guint8 codec_data[2];
12514                 GstBuffer *buf;
12515                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12516
12517                 gint sample_rate_index =
12518                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12519
12520                 /* build AAC codec data */
12521                 codec_data[0] = profile << 3;
12522                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12523                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12524                 codec_data[1] |= (channels & 0xF) << 3;
12525
12526                 buf = gst_buffer_new_and_alloc (2);
12527                 gst_buffer_fill (buf, 0, codec_data, 2);
12528                 gst_caps_set_simple (entry->caps,
12529                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12530                 gst_buffer_unref (buf);
12531               }
12532             }
12533             break;
12534           }
12535           case FOURCC_lpcm:
12536           case FOURCC_in24:
12537           case FOURCC_in32:
12538           case FOURCC_fl32:
12539           case FOURCC_fl64:
12540           case FOURCC_s16l:
12541             /* Fully handled elsewhere */
12542             break;
12543           default:
12544             GST_INFO_OBJECT (qtdemux,
12545                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12546             break;
12547         }
12548       }
12549       GST_INFO_OBJECT (qtdemux,
12550           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12551           GST_FOURCC_ARGS (fourcc), entry->caps);
12552
12553     } else if (stream->subtype == FOURCC_strm) {
12554       if (fourcc == FOURCC_rtsp) {
12555         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12556       } else {
12557         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12558             GST_FOURCC_ARGS (fourcc));
12559         goto unknown_stream;
12560       }
12561       entry->sampled = TRUE;
12562     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12563         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12564         || stream->subtype == FOURCC_clcp) {
12565
12566       entry->sampled = TRUE;
12567       entry->sparse = TRUE;
12568
12569       entry->caps =
12570           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12571           &codec);
12572       if (codec) {
12573         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12574             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12575         g_free (codec);
12576         codec = NULL;
12577       }
12578
12579       /* hunt for sort-of codec data */
12580       switch (fourcc) {
12581         case FOURCC_mp4s:
12582         {
12583           GNode *mp4s = NULL;
12584           GNode *esds = NULL;
12585
12586           /* look for palette in a stsd->mp4s->esds sub-atom */
12587           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12588           if (mp4s)
12589             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12590           if (esds == NULL) {
12591             /* Invalid STSD */
12592             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12593             break;
12594           }
12595
12596           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12597               stream->stream_tags);
12598           break;
12599         }
12600         default:
12601           GST_INFO_OBJECT (qtdemux,
12602               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12603           break;
12604       }
12605       GST_INFO_OBJECT (qtdemux,
12606           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12607           GST_FOURCC_ARGS (fourcc), entry->caps);
12608     } else {
12609       /* everything in 1 sample */
12610       entry->sampled = TRUE;
12611
12612       entry->caps =
12613           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12614           &codec);
12615
12616       if (entry->caps == NULL)
12617         goto unknown_stream;
12618
12619       if (codec) {
12620         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12621             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12622         g_free (codec);
12623         codec = NULL;
12624       }
12625     }
12626
12627     /* promote to sampled format */
12628     if (entry->fourcc == FOURCC_samr) {
12629       /* force mono 8000 Hz for AMR */
12630       entry->sampled = TRUE;
12631       entry->n_channels = 1;
12632       entry->rate = 8000;
12633     } else if (entry->fourcc == FOURCC_sawb) {
12634       /* force mono 16000 Hz for AMR-WB */
12635       entry->sampled = TRUE;
12636       entry->n_channels = 1;
12637       entry->rate = 16000;
12638     } else if (entry->fourcc == FOURCC_mp4a) {
12639       entry->sampled = TRUE;
12640     }
12641
12642
12643     stsd_entry_data += len;
12644     remaining_stsd_len -= len;
12645
12646   }
12647
12648   /* collect sample information */
12649   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12650     goto samples_failed;
12651
12652   if (qtdemux->fragmented) {
12653     guint64 offset;
12654
12655     /* need all moov samples as basis; probably not many if any at all */
12656     /* prevent moof parsing taking of at this time */
12657     offset = qtdemux->moof_offset;
12658     qtdemux->moof_offset = 0;
12659     if (stream->n_samples &&
12660         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12661       qtdemux->moof_offset = offset;
12662       goto samples_failed;
12663     }
12664     qtdemux->moof_offset = 0;
12665     /* movie duration more reliable in this case (e.g. mehd) */
12666     if (qtdemux->segment.duration &&
12667         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12668       stream->duration =
12669           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12670   }
12671
12672   /* configure segments */
12673   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12674     goto segments_failed;
12675
12676   /* add some language tag, if useful */
12677   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12678       strcmp (stream->lang_id, "und")) {
12679     const gchar *lang_code;
12680
12681     /* convert ISO 639-2 code to ISO 639-1 */
12682     lang_code = gst_tag_get_language_code (stream->lang_id);
12683     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12684         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12685   }
12686
12687   /* Check for UDTA tags */
12688   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12689     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12690   }
12691
12692   /* Insert and sort new stream in track-id order.
12693    * This will help in comparing old/new streams during stream update check */
12694   g_ptr_array_add (qtdemux->active_streams, stream);
12695   g_ptr_array_sort (qtdemux->active_streams,
12696       (GCompareFunc) qtdemux_track_id_compare_func);
12697   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12698       QTDEMUX_N_STREAMS (qtdemux));
12699
12700   return TRUE;
12701
12702 /* ERRORS */
12703 corrupt_file:
12704   {
12705     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12706         (_("This file is corrupt and cannot be played.")), (NULL));
12707     if (stream)
12708       gst_qtdemux_stream_unref (stream);
12709     return FALSE;
12710   }
12711 error_encrypted:
12712   {
12713     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12714     gst_qtdemux_stream_unref (stream);
12715     return FALSE;
12716   }
12717 samples_failed:
12718 segments_failed:
12719   {
12720     /* we posted an error already */
12721     /* free stbl sub-atoms */
12722     gst_qtdemux_stbl_free (stream);
12723     gst_qtdemux_stream_unref (stream);
12724     return FALSE;
12725   }
12726 existing_stream:
12727   {
12728     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12729         track_id);
12730     return TRUE;
12731   }
12732 unknown_stream:
12733   {
12734     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12735         GST_FOURCC_ARGS (stream->subtype));
12736     gst_qtdemux_stream_unref (stream);
12737     return TRUE;
12738   }
12739 }
12740
12741 /* If we can estimate the overall bitrate, and don't have information about the
12742  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12743  * the overall bitrate minus the sum of the bitrates of all other streams. This
12744  * should be useful for the common case where we have one audio and one video
12745  * stream and can estimate the bitrate of one, but not the other. */
12746 static void
12747 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12748 {
12749   QtDemuxStream *stream = NULL;
12750   gint64 size, sys_bitrate, sum_bitrate = 0;
12751   GstClockTime duration;
12752   guint bitrate;
12753   gint i;
12754
12755   if (qtdemux->fragmented)
12756     return;
12757
12758   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12759
12760   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12761       || size <= 0) {
12762     GST_DEBUG_OBJECT (qtdemux,
12763         "Size in bytes of the stream not known - bailing");
12764     return;
12765   }
12766
12767   /* Subtract the header size */
12768   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12769       size, qtdemux->header_size);
12770
12771   if (size < qtdemux->header_size)
12772     return;
12773
12774   size = size - qtdemux->header_size;
12775
12776   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12777     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12778     return;
12779   }
12780
12781   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12782     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12783     switch (str->subtype) {
12784       case FOURCC_soun:
12785       case FOURCC_vide:
12786         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12787             CUR_STREAM (str)->caps);
12788         /* retrieve bitrate, prefer avg then max */
12789         bitrate = 0;
12790         if (str->stream_tags) {
12791           if (gst_tag_list_get_uint (str->stream_tags,
12792                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12793             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12794           if (gst_tag_list_get_uint (str->stream_tags,
12795                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12796             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12797           if (gst_tag_list_get_uint (str->stream_tags,
12798                   GST_TAG_BITRATE, &bitrate))
12799             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12800         }
12801         if (bitrate)
12802           sum_bitrate += bitrate;
12803         else {
12804           if (stream) {
12805             GST_DEBUG_OBJECT (qtdemux,
12806                 ">1 stream with unknown bitrate - bailing");
12807             return;
12808           } else
12809             stream = str;
12810         }
12811
12812       default:
12813         /* For other subtypes, we assume no significant impact on bitrate */
12814         break;
12815     }
12816   }
12817
12818   if (!stream) {
12819     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12820     return;
12821   }
12822
12823   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12824
12825   if (sys_bitrate < sum_bitrate) {
12826     /* This can happen, since sum_bitrate might be derived from maximum
12827      * bitrates and not average bitrates */
12828     GST_DEBUG_OBJECT (qtdemux,
12829         "System bitrate less than sum bitrate - bailing");
12830     return;
12831   }
12832
12833   bitrate = sys_bitrate - sum_bitrate;
12834   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12835       ", Stream bitrate = %u", sys_bitrate, bitrate);
12836
12837   if (!stream->stream_tags)
12838     stream->stream_tags = gst_tag_list_new_empty ();
12839   else
12840     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12841
12842   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12843       GST_TAG_BITRATE, bitrate, NULL);
12844 }
12845
12846 static GstFlowReturn
12847 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12848 {
12849   GstFlowReturn ret = GST_FLOW_OK;
12850   gint i;
12851
12852   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12853
12854   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12855     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12856     guint32 sample_num = 0;
12857
12858     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12859         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12860
12861     if (qtdemux->fragmented) {
12862       /* need all moov samples first */
12863       GST_OBJECT_LOCK (qtdemux);
12864       while (stream->n_samples == 0)
12865         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12866           break;
12867       GST_OBJECT_UNLOCK (qtdemux);
12868     } else {
12869       /* discard any stray moof */
12870       qtdemux->moof_offset = 0;
12871     }
12872
12873     /* prepare braking */
12874     if (ret != GST_FLOW_ERROR)
12875       ret = GST_FLOW_OK;
12876
12877     /* in pull mode, we should have parsed some sample info by now;
12878      * and quite some code will not handle no samples.
12879      * in push mode, we'll just have to deal with it */
12880     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12881       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12882       g_ptr_array_remove_index (qtdemux->active_streams, i);
12883       i--;
12884       continue;
12885     } else if (stream->track_id == qtdemux->chapters_track_id &&
12886         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12887       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12888          so that it doesn't look like a subtitle track */
12889       g_ptr_array_remove_index (qtdemux->active_streams, i);
12890       i--;
12891       continue;
12892     }
12893
12894     /* parse the initial sample for use in setting the frame rate cap */
12895     while (sample_num == 0 && sample_num < stream->n_samples) {
12896       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12897         break;
12898       ++sample_num;
12899     }
12900   }
12901
12902   return ret;
12903 }
12904
12905 static gboolean
12906 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
12907 {
12908   return g_strcmp0 (stream->stream_id, stream_id) == 0;
12909 }
12910
12911 static gboolean
12912 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12913 {
12914   gint i;
12915
12916   /* Different length, updated */
12917   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
12918     return TRUE;
12919
12920   /* streams in list are sorted in track-id order */
12921   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12922     /* Different stream-id, updated */
12923     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
12924             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
12925       return TRUE;
12926   }
12927
12928   return FALSE;
12929 }
12930
12931 static gboolean
12932 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12933     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12934 {
12935   /* Connect old stream's srcpad to new stream */
12936   newstream->pad = oldstream->pad;
12937   oldstream->pad = NULL;
12938
12939   /* unset new_stream to prevent stream-start event */
12940   newstream->new_stream = FALSE;
12941
12942   return gst_qtdemux_configure_stream (qtdemux, newstream);
12943 }
12944
12945 /* g_ptr_array_find_with_equal_func is available since 2.54,
12946  * replacement until we can depend unconditionally on the real one in GLib */
12947 #if !GLIB_CHECK_VERSION(2,54,0)
12948 #define g_ptr_array_find_with_equal_func qtdemux_ptr_array_find_with_equal_func
12949 static gboolean
12950 qtdemux_ptr_array_find_with_equal_func (GPtrArray * haystack,
12951     gconstpointer needle, GEqualFunc equal_func, guint * index_)
12952 {
12953   guint i;
12954
12955   g_return_val_if_fail (haystack != NULL, FALSE);
12956
12957   if (equal_func == NULL)
12958     equal_func = g_direct_equal;
12959
12960   for (i = 0; i < haystack->len; i++) {
12961     if (equal_func (g_ptr_array_index (haystack, i), needle)) {
12962       if (index_ != NULL)
12963         *index_ = i;
12964       return TRUE;
12965     }
12966   }
12967
12968   return FALSE;
12969 }
12970 #endif
12971
12972 static gboolean
12973 qtdemux_update_streams (GstQTDemux * qtdemux)
12974 {
12975   gint i;
12976   g_assert (qtdemux->streams_aware);
12977
12978   /* At below, figure out which stream in active_streams has identical stream-id
12979    * with that of in old_streams. If there is matching stream-id,
12980    * corresponding newstream will not be exposed again,
12981    * but demux will reuse srcpad of matched old stream
12982    *
12983    * active_streams : newly created streams from the latest moov
12984    * old_streams : existing streams (belong to previous moov)
12985    */
12986
12987   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12988     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12989     QtDemuxStream *oldstream = NULL;
12990     guint target;
12991
12992     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12993         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12994
12995     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
12996             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
12997       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
12998
12999       /* null pad stream cannot be reused */
13000       if (oldstream->pad == NULL)
13001         oldstream = NULL;
13002     }
13003
13004     if (oldstream) {
13005       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13006
13007       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13008         return FALSE;
13009
13010       /* we don't need to preserve order of old streams */
13011       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13012     } else {
13013       GstTagList *list;
13014
13015       /* now we have all info and can expose */
13016       list = stream->stream_tags;
13017       stream->stream_tags = NULL;
13018       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13019         return FALSE;
13020     }
13021   }
13022
13023   return TRUE;
13024 }
13025
13026 /* Must be called with expose lock */
13027 static GstFlowReturn
13028 qtdemux_expose_streams (GstQTDemux * qtdemux)
13029 {
13030   gint i;
13031
13032   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13033
13034   if (!qtdemux_is_streams_update (qtdemux)) {
13035     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13036     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13037       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13038       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13039       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13040         return GST_FLOW_ERROR;
13041     }
13042
13043     g_ptr_array_set_size (qtdemux->old_streams, 0);
13044     qtdemux->need_segment = TRUE;
13045
13046     return GST_FLOW_OK;
13047   }
13048
13049   if (qtdemux->streams_aware) {
13050     if (!qtdemux_update_streams (qtdemux))
13051       return GST_FLOW_ERROR;
13052   } else {
13053     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13054       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13055       GstTagList *list;
13056
13057       /* now we have all info and can expose */
13058       list = stream->stream_tags;
13059       stream->stream_tags = NULL;
13060       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13061         return GST_FLOW_ERROR;
13062
13063     }
13064   }
13065
13066   gst_qtdemux_guess_bitrate (qtdemux);
13067
13068   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13069
13070   /* If we have still old_streams, it's no more used stream */
13071   for (i = 0; i < qtdemux->old_streams->len; i++) {
13072     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13073
13074     if (stream->pad) {
13075       GstEvent *event;
13076
13077       event = gst_event_new_eos ();
13078       if (qtdemux->segment_seqnum)
13079         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13080
13081       gst_pad_push_event (stream->pad, event);
13082     }
13083   }
13084
13085   g_ptr_array_set_size (qtdemux->old_streams, 0);
13086
13087   /* check if we should post a redirect in case there is a single trak
13088    * and it is a redirecting trak */
13089   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13090       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13091     GstMessage *m;
13092
13093     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13094         "an external content");
13095     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13096         gst_structure_new ("redirect",
13097             "new-location", G_TYPE_STRING,
13098             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13099     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13100     g_free (qtdemux->redirect_location);
13101     qtdemux->redirect_location =
13102         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13103   }
13104
13105   g_ptr_array_foreach (qtdemux->active_streams,
13106       (GFunc) qtdemux_do_allocation, qtdemux);
13107
13108   qtdemux->need_segment = TRUE;
13109
13110   qtdemux->exposed = TRUE;
13111   return GST_FLOW_OK;
13112 }
13113
13114 typedef struct
13115 {
13116   GstStructure *structure;      /* helper for sort function */
13117   gchar *location;
13118   guint min_req_bitrate;
13119   guint min_req_qt_version;
13120 } GstQtReference;
13121
13122 static gint
13123 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13124 {
13125   GstQtReference *ref_a = (GstQtReference *) a;
13126   GstQtReference *ref_b = (GstQtReference *) b;
13127
13128   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13129     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13130
13131   /* known bitrates go before unknown; higher bitrates go first */
13132   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13133 }
13134
13135 /* sort the redirects and post a message for the application.
13136  */
13137 static void
13138 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13139 {
13140   GstQtReference *best;
13141   GstStructure *s;
13142   GstMessage *msg;
13143   GValue list_val = { 0, };
13144   GList *l;
13145
13146   g_assert (references != NULL);
13147
13148   references = g_list_sort (references, qtdemux_redirects_sort_func);
13149
13150   best = (GstQtReference *) references->data;
13151
13152   g_value_init (&list_val, GST_TYPE_LIST);
13153
13154   for (l = references; l != NULL; l = l->next) {
13155     GstQtReference *ref = (GstQtReference *) l->data;
13156     GValue struct_val = { 0, };
13157
13158     ref->structure = gst_structure_new ("redirect",
13159         "new-location", G_TYPE_STRING, ref->location, NULL);
13160
13161     if (ref->min_req_bitrate > 0) {
13162       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13163           ref->min_req_bitrate, NULL);
13164     }
13165
13166     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13167     g_value_set_boxed (&struct_val, ref->structure);
13168     gst_value_list_append_value (&list_val, &struct_val);
13169     g_value_unset (&struct_val);
13170     /* don't free anything here yet, since we need best->structure below */
13171   }
13172
13173   g_assert (best != NULL);
13174   s = gst_structure_copy (best->structure);
13175
13176   if (g_list_length (references) > 1) {
13177     gst_structure_set_value (s, "locations", &list_val);
13178   }
13179
13180   g_value_unset (&list_val);
13181
13182   for (l = references; l != NULL; l = l->next) {
13183     GstQtReference *ref = (GstQtReference *) l->data;
13184
13185     gst_structure_free (ref->structure);
13186     g_free (ref->location);
13187     g_free (ref);
13188   }
13189   g_list_free (references);
13190
13191   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13192   g_free (qtdemux->redirect_location);
13193   qtdemux->redirect_location =
13194       g_strdup (gst_structure_get_string (s, "new-location"));
13195   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13196   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13197 }
13198
13199 /* look for redirect nodes, collect all redirect information and
13200  * process it.
13201  */
13202 static gboolean
13203 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13204 {
13205   GNode *rmra, *rmda, *rdrf;
13206
13207   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13208   if (rmra) {
13209     GList *redirects = NULL;
13210
13211     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13212     while (rmda) {
13213       GstQtReference ref = { NULL, NULL, 0, 0 };
13214       GNode *rmdr, *rmvc;
13215
13216       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13217         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13218         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13219             ref.min_req_bitrate);
13220       }
13221
13222       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13223         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13224         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13225
13226 #ifndef GST_DISABLE_GST_DEBUG
13227         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13228 #endif
13229         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13230
13231         GST_LOG_OBJECT (qtdemux,
13232             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13233             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13234             bitmask, check_type);
13235         if (package == FOURCC_qtim && check_type == 0) {
13236           ref.min_req_qt_version = version;
13237         }
13238       }
13239
13240       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13241       if (rdrf) {
13242         guint32 ref_type;
13243         guint8 *ref_data;
13244         guint ref_len;
13245
13246         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13247         if (ref_len > 20) {
13248           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13249           ref_data = (guint8 *) rdrf->data + 20;
13250           if (ref_type == FOURCC_alis) {
13251             guint record_len, record_version, fn_len;
13252
13253             if (ref_len > 70) {
13254               /* MacOSX alias record, google for alias-layout.txt */
13255               record_len = QT_UINT16 (ref_data + 4);
13256               record_version = QT_UINT16 (ref_data + 4 + 2);
13257               fn_len = QT_UINT8 (ref_data + 50);
13258               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13259                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13260               }
13261             } else {
13262               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13263                   ref_len);
13264             }
13265           } else if (ref_type == FOURCC_url_) {
13266             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13267           } else {
13268             GST_DEBUG_OBJECT (qtdemux,
13269                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13270                 GST_FOURCC_ARGS (ref_type));
13271           }
13272           if (ref.location != NULL) {
13273             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13274             redirects =
13275                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13276           } else {
13277             GST_WARNING_OBJECT (qtdemux,
13278                 "Failed to extract redirect location from rdrf atom");
13279           }
13280         } else {
13281           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13282         }
13283       }
13284
13285       /* look for others */
13286       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13287     }
13288
13289     if (redirects != NULL) {
13290       qtdemux_process_redirects (qtdemux, redirects);
13291     }
13292   }
13293   return TRUE;
13294 }
13295
13296 static GstTagList *
13297 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13298 {
13299   const gchar *fmt;
13300
13301   if (tags == NULL) {
13302     tags = gst_tag_list_new_empty ();
13303     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13304   }
13305
13306   if (qtdemux->major_brand == FOURCC_mjp2)
13307     fmt = "Motion JPEG 2000";
13308   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13309     fmt = "3GP";
13310   else if (qtdemux->major_brand == FOURCC_qt__)
13311     fmt = "Quicktime";
13312   else if (qtdemux->fragmented)
13313     fmt = "ISO fMP4";
13314   else
13315     fmt = "ISO MP4/M4A";
13316
13317   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13318       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13319
13320   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13321       fmt, NULL);
13322
13323   return tags;
13324 }
13325
13326 /* we have read the complete moov node now.
13327  * This function parses all of the relevant info, creates the traks and
13328  * prepares all data structures for playback
13329  */
13330 static gboolean
13331 qtdemux_parse_tree (GstQTDemux * qtdemux)
13332 {
13333   GNode *mvhd;
13334   GNode *trak;
13335   GNode *udta;
13336   GNode *mvex;
13337   GNode *pssh;
13338   guint64 creation_time;
13339   GstDateTime *datetime = NULL;
13340   gint version;
13341
13342   /* make sure we have a usable taglist */
13343   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13344
13345   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13346   if (mvhd == NULL) {
13347     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13348     return qtdemux_parse_redirects (qtdemux);
13349   }
13350
13351   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13352   if (version == 1) {
13353     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13354     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13355     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13356   } else if (version == 0) {
13357     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13358     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13359     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13360   } else {
13361     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13362     return FALSE;
13363   }
13364
13365   /* Moving qt creation time (secs since 1904) to unix time */
13366   if (creation_time != 0) {
13367     /* Try to use epoch first as it should be faster and more commonly found */
13368     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13369       gint64 now_s;
13370
13371       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13372       /* some data cleansing sanity */
13373       now_s = g_get_real_time () / G_USEC_PER_SEC;
13374       if (now_s + 24 * 3600 < creation_time) {
13375         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13376       } else {
13377         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13378       }
13379     } else {
13380       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13381       GDateTime *dt, *dt_local;
13382
13383       dt = g_date_time_add_seconds (base_dt, creation_time);
13384       dt_local = g_date_time_to_local (dt);
13385       datetime = gst_date_time_new_from_g_date_time (dt_local);
13386
13387       g_date_time_unref (base_dt);
13388       g_date_time_unref (dt);
13389     }
13390   }
13391   if (datetime) {
13392     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13393     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13394         datetime, NULL);
13395     gst_date_time_unref (datetime);
13396   }
13397
13398   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13399   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13400
13401   /* check for fragmented file and get some (default) data */
13402   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13403   if (mvex) {
13404     GNode *mehd;
13405     GstByteReader mehd_data;
13406
13407     /* let track parsing or anyone know weird stuff might happen ... */
13408     qtdemux->fragmented = TRUE;
13409
13410     /* compensate for total duration */
13411     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13412     if (mehd)
13413       qtdemux_parse_mehd (qtdemux, &mehd_data);
13414   }
13415
13416   /* Update the movie segment duration, unless it was directly given to us
13417    * by upstream. Otherwise let it as is, as we don't want to mangle the
13418    * duration provided by upstream that may come e.g. from a MPD file. */
13419   if (!qtdemux->upstream_format_is_time) {
13420     GstClockTime duration;
13421     /* set duration in the segment info */
13422     gst_qtdemux_get_duration (qtdemux, &duration);
13423     qtdemux->segment.duration = duration;
13424     /* also do not exceed duration; stop is set that way post seek anyway,
13425      * and segment activation falls back to duration,
13426      * whereas loop only checks stop, so let's align this here as well */
13427     qtdemux->segment.stop = duration;
13428   }
13429
13430   /* parse all traks */
13431   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13432   while (trak) {
13433     qtdemux_parse_trak (qtdemux, trak);
13434     /* iterate all siblings */
13435     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13436   }
13437
13438   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13439
13440   /* find tags */
13441   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13442   if (udta) {
13443     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13444   } else {
13445     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13446   }
13447
13448   /* maybe also some tags in meta box */
13449   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13450   if (udta) {
13451     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13452     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13453   } else {
13454     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13455   }
13456
13457   /* parse any protection system info */
13458   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13459   while (pssh) {
13460     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13461     qtdemux_parse_pssh (qtdemux, pssh);
13462     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13463   }
13464
13465   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13466
13467   return TRUE;
13468 }
13469
13470 /* taken from ffmpeg */
13471 static int
13472 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13473 {
13474   int count = 4;
13475   int len = 0;
13476
13477   while (count--) {
13478     int c;
13479
13480     if (ptr >= end)
13481       return -1;
13482
13483     c = *ptr++;
13484     len = (len << 7) | (c & 0x7f);
13485     if (!(c & 0x80))
13486       break;
13487   }
13488   *end_out = ptr;
13489   return len;
13490 }
13491
13492 static GList *
13493 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13494     gsize codec_data_size)
13495 {
13496   GList *list = NULL;
13497   guint8 *p = codec_data;
13498   gint i, offset, num_packets;
13499   guint *length, last;
13500
13501   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13502
13503   if (codec_data == NULL || codec_data_size == 0)
13504     goto error;
13505
13506   /* start of the stream and vorbis audio or theora video, need to
13507    * send the codec_priv data as first three packets */
13508   num_packets = p[0] + 1;
13509   GST_DEBUG_OBJECT (qtdemux,
13510       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13511       (guint) num_packets, codec_data_size);
13512
13513   /* Let's put some limits, Don't think there even is a xiph codec
13514    * with more than 3-4 headers */
13515   if (G_UNLIKELY (num_packets > 16)) {
13516     GST_WARNING_OBJECT (qtdemux,
13517         "Unlikely number of xiph headers, most likely not valid");
13518     goto error;
13519   }
13520
13521   length = g_alloca (num_packets * sizeof (guint));
13522   last = 0;
13523   offset = 1;
13524
13525   /* first packets, read length values */
13526   for (i = 0; i < num_packets - 1; i++) {
13527     length[i] = 0;
13528     while (offset < codec_data_size) {
13529       length[i] += p[offset];
13530       if (p[offset++] != 0xff)
13531         break;
13532     }
13533     last += length[i];
13534   }
13535   if (offset + last > codec_data_size)
13536     goto error;
13537
13538   /* last packet is the remaining size */
13539   length[i] = codec_data_size - offset - last;
13540
13541   for (i = 0; i < num_packets; i++) {
13542     GstBuffer *hdr;
13543
13544     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13545
13546     if (offset + length[i] > codec_data_size)
13547       goto error;
13548
13549     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13550     list = g_list_append (list, hdr);
13551
13552     offset += length[i];
13553   }
13554
13555   return list;
13556
13557   /* ERRORS */
13558 error:
13559   {
13560     if (list != NULL)
13561       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13562     return NULL;
13563   }
13564
13565 }
13566
13567 /* this can change the codec originally present in @list */
13568 static void
13569 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13570     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13571 {
13572   int len = QT_UINT32 (esds->data);
13573   guint8 *ptr = esds->data;
13574   guint8 *end = ptr + len;
13575   int tag;
13576   guint8 *data_ptr = NULL;
13577   int data_len = 0;
13578   guint8 object_type_id = 0;
13579   guint8 stream_type = 0;
13580   const char *codec_name = NULL;
13581   GstCaps *caps = NULL;
13582
13583   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13584   ptr += 8;
13585   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13586   ptr += 4;
13587   while (ptr + 1 < end) {
13588     tag = QT_UINT8 (ptr);
13589     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13590     ptr++;
13591     len = read_descr_size (ptr, end, &ptr);
13592     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13593
13594     /* Check the stated amount of data is available for reading */
13595     if (len < 0 || ptr + len > end)
13596       break;
13597
13598     switch (tag) {
13599       case ES_DESCRIPTOR_TAG:
13600         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13601         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13602         ptr += 3;
13603         break;
13604       case DECODER_CONFIG_DESC_TAG:{
13605         guint max_bitrate, avg_bitrate;
13606
13607         object_type_id = QT_UINT8 (ptr);
13608         stream_type = QT_UINT8 (ptr + 1) >> 2;
13609         max_bitrate = QT_UINT32 (ptr + 5);
13610         avg_bitrate = QT_UINT32 (ptr + 9);
13611         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13612         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13613         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13614         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13615         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13616         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13617           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13618               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13619         }
13620         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13621           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13622               avg_bitrate, NULL);
13623         }
13624         ptr += 13;
13625         break;
13626       }
13627       case DECODER_SPECIFIC_INFO_TAG:
13628         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13629         if (object_type_id == 0xe0 && len == 0x40) {
13630           guint8 *data;
13631           GstStructure *s;
13632           guint32 clut[16];
13633           gint i;
13634
13635           GST_DEBUG_OBJECT (qtdemux,
13636               "Have VOBSUB palette. Creating palette event");
13637           /* move to decConfigDescr data and read palette */
13638           data = ptr;
13639           for (i = 0; i < 16; i++) {
13640             clut[i] = QT_UINT32 (data);
13641             data += 4;
13642           }
13643
13644           s = gst_structure_new ("application/x-gst-dvd", "event",
13645               G_TYPE_STRING, "dvd-spu-clut-change",
13646               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13647               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13648               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13649               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13650               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13651               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13652               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13653               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13654               NULL);
13655
13656           /* store event and trigger custom processing */
13657           stream->pending_event =
13658               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13659         } else {
13660           /* Generic codec_data handler puts it on the caps */
13661           data_ptr = ptr;
13662           data_len = len;
13663         }
13664
13665         ptr += len;
13666         break;
13667       case SL_CONFIG_DESC_TAG:
13668         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13669         ptr += 1;
13670         break;
13671       default:
13672         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13673             tag);
13674         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13675         ptr += len;
13676         break;
13677     }
13678   }
13679
13680   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13681    * in use, and should also be used to override some other parameters for some
13682    * codecs. */
13683   switch (object_type_id) {
13684     case 0x20:                 /* MPEG-4 */
13685       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13686        * profile_and_level_indication */
13687       if (data_ptr != NULL && data_len >= 5 &&
13688           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13689         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13690             data_ptr + 4, data_len - 4);
13691       }
13692       break;                    /* Nothing special needed here */
13693     case 0x21:                 /* H.264 */
13694       codec_name = "H.264 / AVC";
13695       caps = gst_caps_new_simple ("video/x-h264",
13696           "stream-format", G_TYPE_STRING, "avc",
13697           "alignment", G_TYPE_STRING, "au", NULL);
13698       break;
13699     case 0x40:                 /* AAC (any) */
13700     case 0x66:                 /* AAC Main */
13701     case 0x67:                 /* AAC LC */
13702     case 0x68:                 /* AAC SSR */
13703       /* Override channels and rate based on the codec_data, as it's often
13704        * wrong. */
13705       /* Only do so for basic setup without HE-AAC extension */
13706       if (data_ptr && data_len == 2) {
13707         guint channels, rate;
13708
13709         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13710         if (channels > 0)
13711           entry->n_channels = channels;
13712
13713         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13714         if (rate > 0)
13715           entry->rate = rate;
13716       }
13717
13718       /* Set level and profile if possible */
13719       if (data_ptr != NULL && data_len >= 2) {
13720         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13721             data_ptr, data_len);
13722       } else {
13723         const gchar *profile_str = NULL;
13724         GstBuffer *buffer;
13725         GstMapInfo map;
13726         guint8 *codec_data;
13727         gint rate_idx, profile;
13728
13729         /* No codec_data, let's invent something.
13730          * FIXME: This is wrong for SBR! */
13731
13732         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13733
13734         buffer = gst_buffer_new_and_alloc (2);
13735         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13736         codec_data = map.data;
13737
13738         rate_idx =
13739             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13740             (stream)->rate);
13741
13742         switch (object_type_id) {
13743           case 0x66:
13744             profile_str = "main";
13745             profile = 0;
13746             break;
13747           case 0x67:
13748             profile_str = "lc";
13749             profile = 1;
13750             break;
13751           case 0x68:
13752             profile_str = "ssr";
13753             profile = 2;
13754             break;
13755           default:
13756             profile = 3;
13757             break;
13758         }
13759
13760         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13761         codec_data[1] =
13762             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13763
13764         gst_buffer_unmap (buffer, &map);
13765         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13766             GST_TYPE_BUFFER, buffer, NULL);
13767         gst_buffer_unref (buffer);
13768
13769         if (profile_str) {
13770           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13771               G_TYPE_STRING, profile_str, NULL);
13772         }
13773       }
13774       break;
13775     case 0x60:                 /* MPEG-2, various profiles */
13776     case 0x61:
13777     case 0x62:
13778     case 0x63:
13779     case 0x64:
13780     case 0x65:
13781       codec_name = "MPEG-2 video";
13782       caps = gst_caps_new_simple ("video/mpeg",
13783           "mpegversion", G_TYPE_INT, 2,
13784           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13785       break;
13786     case 0x69:                 /* MPEG-2 BC audio */
13787     case 0x6B:                 /* MPEG-1 audio */
13788       caps = gst_caps_new_simple ("audio/mpeg",
13789           "mpegversion", G_TYPE_INT, 1, NULL);
13790       codec_name = "MPEG-1 audio";
13791       break;
13792     case 0x6A:                 /* MPEG-1 */
13793       codec_name = "MPEG-1 video";
13794       caps = gst_caps_new_simple ("video/mpeg",
13795           "mpegversion", G_TYPE_INT, 1,
13796           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13797       break;
13798     case 0x6C:                 /* MJPEG */
13799       caps =
13800           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13801           NULL);
13802       codec_name = "Motion-JPEG";
13803       break;
13804     case 0x6D:                 /* PNG */
13805       caps =
13806           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13807           NULL);
13808       codec_name = "PNG still images";
13809       break;
13810     case 0x6E:                 /* JPEG2000 */
13811       codec_name = "JPEG-2000";
13812       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13813       break;
13814     case 0xA4:                 /* Dirac */
13815       codec_name = "Dirac";
13816       caps = gst_caps_new_empty_simple ("video/x-dirac");
13817       break;
13818     case 0xA5:                 /* AC3 */
13819       codec_name = "AC-3 audio";
13820       caps = gst_caps_new_simple ("audio/x-ac3",
13821           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13822       break;
13823     case 0xA9:                 /* AC3 */
13824       codec_name = "DTS audio";
13825       caps = gst_caps_new_simple ("audio/x-dts",
13826           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13827       break;
13828     case 0xDD:
13829       if (stream_type == 0x05 && data_ptr) {
13830         GList *headers =
13831             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
13832         if (headers) {
13833           GList *tmp;
13834           GValue arr_val = G_VALUE_INIT;
13835           GValue buf_val = G_VALUE_INIT;
13836           GstStructure *s;
13837
13838           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
13839           codec_name = "Vorbis";
13840           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
13841           g_value_init (&arr_val, GST_TYPE_ARRAY);
13842           g_value_init (&buf_val, GST_TYPE_BUFFER);
13843           for (tmp = headers; tmp; tmp = tmp->next) {
13844             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
13845             gst_value_array_append_value (&arr_val, &buf_val);
13846           }
13847           s = gst_caps_get_structure (caps, 0);
13848           gst_structure_take_value (s, "streamheader", &arr_val);
13849           g_value_unset (&buf_val);
13850           g_list_free (headers);
13851
13852           data_ptr = NULL;
13853           data_len = 0;
13854         }
13855       }
13856       break;
13857     case 0xE1:                 /* QCELP */
13858       /* QCELP, the codec_data is a riff tag (little endian) with
13859        * 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). */
13860       caps = gst_caps_new_empty_simple ("audio/qcelp");
13861       codec_name = "QCELP";
13862       break;
13863     default:
13864       break;
13865   }
13866
13867   /* If we have a replacement caps, then change our caps for this stream */
13868   if (caps) {
13869     gst_caps_unref (entry->caps);
13870     entry->caps = caps;
13871   }
13872
13873   if (codec_name && list)
13874     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13875         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13876
13877   /* Add the codec_data attribute to caps, if we have it */
13878   if (data_ptr) {
13879     GstBuffer *buffer;
13880
13881     buffer = gst_buffer_new_and_alloc (data_len);
13882     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13883
13884     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13885     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13886
13887     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13888         buffer, NULL);
13889     gst_buffer_unref (buffer);
13890   }
13891
13892 }
13893
13894 static inline GstCaps *
13895 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13896 {
13897   GstCaps *caps;
13898   guint i;
13899   char *s, fourstr[5];
13900
13901   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13902   for (i = 0; i < 4; i++) {
13903     if (!g_ascii_isalnum (fourstr[i]))
13904       fourstr[i] = '_';
13905   }
13906   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13907   caps = gst_caps_new_empty_simple (s);
13908   g_free (s);
13909   return caps;
13910 }
13911
13912 #define _codec(name) \
13913   do { \
13914     if (codec_name) { \
13915       *codec_name = g_strdup (name); \
13916     } \
13917   } while (0)
13918
13919 static GstCaps *
13920 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13921     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13922     const guint8 * stsd_entry_data, gchar ** codec_name)
13923 {
13924   GstCaps *caps = NULL;
13925   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13926
13927   switch (fourcc) {
13928     case FOURCC_png:
13929       _codec ("PNG still images");
13930       caps = gst_caps_new_empty_simple ("image/png");
13931       break;
13932     case FOURCC_jpeg:
13933       _codec ("JPEG still images");
13934       caps =
13935           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13936           NULL);
13937       break;
13938     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13939     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13940     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13941     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13942       _codec ("Motion-JPEG");
13943       caps =
13944           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13945           NULL);
13946       break;
13947     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13948       _codec ("Motion-JPEG format B");
13949       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13950       break;
13951     case FOURCC_mjp2:
13952       _codec ("JPEG-2000");
13953       /* override to what it should be according to spec, avoid palette_data */
13954       entry->bits_per_sample = 24;
13955       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13956       break;
13957     case FOURCC_SVQ3:
13958       _codec ("Sorensen video v.3");
13959       caps = gst_caps_new_simple ("video/x-svq",
13960           "svqversion", G_TYPE_INT, 3, NULL);
13961       break;
13962     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13963     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13964       _codec ("Sorensen video v.1");
13965       caps = gst_caps_new_simple ("video/x-svq",
13966           "svqversion", G_TYPE_INT, 1, NULL);
13967       break;
13968     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13969       caps = gst_caps_new_empty_simple ("video/x-raw");
13970       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13971       _codec ("Windows Raw RGB");
13972       stream->alignment = 32;
13973       break;
13974     case FOURCC_raw_:
13975     {
13976       guint16 bps;
13977
13978       bps = QT_UINT16 (stsd_entry_data + 82);
13979       switch (bps) {
13980         case 15:
13981           format = GST_VIDEO_FORMAT_RGB15;
13982           break;
13983         case 16:
13984           format = GST_VIDEO_FORMAT_RGB16;
13985           break;
13986         case 24:
13987           format = GST_VIDEO_FORMAT_RGB;
13988           break;
13989         case 32:
13990           format = GST_VIDEO_FORMAT_ARGB;
13991           break;
13992         default:
13993           /* unknown */
13994           break;
13995       }
13996       break;
13997     }
13998     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13999       format = GST_VIDEO_FORMAT_I420;
14000       break;
14001     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14002     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14003       format = GST_VIDEO_FORMAT_I420;
14004       break;
14005     case FOURCC_2vuy:
14006     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14007       format = GST_VIDEO_FORMAT_UYVY;
14008       break;
14009     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14010       format = GST_VIDEO_FORMAT_v308;
14011       break;
14012     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14013       format = GST_VIDEO_FORMAT_v216;
14014       break;
14015     case FOURCC_v210:
14016       format = GST_VIDEO_FORMAT_v210;
14017       break;
14018     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14019       format = GST_VIDEO_FORMAT_r210;
14020       break;
14021       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14022          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14023          format = GST_VIDEO_FORMAT_v410;
14024          break;
14025        */
14026       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14027        * but different order than AYUV
14028        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14029        format = GST_VIDEO_FORMAT_v408;
14030        break;
14031        */
14032     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14033     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14034       _codec ("MPEG-1 video");
14035       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14036           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14037       break;
14038     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14039     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14040     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14041     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14042     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14043     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14044     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14045     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14046     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14047     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14048     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14049     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14050     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14051     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14052     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14053     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14054     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14055     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14056     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14057     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14058     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14059     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14060     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14061     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14062     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14063     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14064     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14065     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14066     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14067     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14068     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14069     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14070     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14071     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14072     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14073     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14074     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14075     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14076     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14077     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14078     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14079     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14080     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14081     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14082     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14083     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14084     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14085       _codec ("MPEG-2 video");
14086       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14087           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14088       break;
14089     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14090       _codec ("GIF still images");
14091       caps = gst_caps_new_empty_simple ("image/gif");
14092       break;
14093     case FOURCC_h263:
14094     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14095     case FOURCC_s263:
14096     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14097       _codec ("H.263");
14098       /* ffmpeg uses the height/width props, don't know why */
14099       caps = gst_caps_new_simple ("video/x-h263",
14100           "variant", G_TYPE_STRING, "itu", NULL);
14101       break;
14102     case FOURCC_mp4v:
14103     case FOURCC_MP4V:
14104       _codec ("MPEG-4 video");
14105       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14106           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14107       break;
14108     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14109     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14110       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14111       caps = gst_caps_new_simple ("video/x-msmpeg",
14112           "msmpegversion", G_TYPE_INT, 43, NULL);
14113       break;
14114     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14115       _codec ("DivX 3");
14116       caps = gst_caps_new_simple ("video/x-divx",
14117           "divxversion", G_TYPE_INT, 3, NULL);
14118       break;
14119     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14120     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14121       _codec ("DivX 4");
14122       caps = gst_caps_new_simple ("video/x-divx",
14123           "divxversion", G_TYPE_INT, 4, NULL);
14124       break;
14125     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14126       _codec ("DivX 5");
14127       caps = gst_caps_new_simple ("video/x-divx",
14128           "divxversion", G_TYPE_INT, 5, NULL);
14129       break;
14130
14131     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14132       _codec ("FFV1");
14133       caps = gst_caps_new_simple ("video/x-ffv",
14134           "ffvversion", G_TYPE_INT, 1, NULL);
14135       break;
14136
14137     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14138     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14139     case FOURCC_XVID:
14140     case FOURCC_xvid:
14141     case FOURCC_FMP4:
14142     case FOURCC_fmp4:
14143     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14144       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14145           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14146       _codec ("MPEG-4");
14147       break;
14148
14149     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14150       _codec ("Cinepak");
14151       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14152       break;
14153     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14154       _codec ("Apple QuickDraw");
14155       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14156       break;
14157     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14158       _codec ("Apple video");
14159       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14160       break;
14161     case FOURCC_H264:
14162     case FOURCC_avc1:
14163       _codec ("H.264 / AVC");
14164       caps = gst_caps_new_simple ("video/x-h264",
14165           "stream-format", G_TYPE_STRING, "avc",
14166           "alignment", G_TYPE_STRING, "au", NULL);
14167       break;
14168     case FOURCC_avc3:
14169       _codec ("H.264 / AVC");
14170       caps = gst_caps_new_simple ("video/x-h264",
14171           "stream-format", G_TYPE_STRING, "avc3",
14172           "alignment", G_TYPE_STRING, "au", NULL);
14173       break;
14174     case FOURCC_H265:
14175     case FOURCC_hvc1:
14176       _codec ("H.265 / HEVC");
14177       caps = gst_caps_new_simple ("video/x-h265",
14178           "stream-format", G_TYPE_STRING, "hvc1",
14179           "alignment", G_TYPE_STRING, "au", NULL);
14180       break;
14181     case FOURCC_hev1:
14182       _codec ("H.265 / HEVC");
14183       caps = gst_caps_new_simple ("video/x-h265",
14184           "stream-format", G_TYPE_STRING, "hev1",
14185           "alignment", G_TYPE_STRING, "au", NULL);
14186       break;
14187     case FOURCC_rle_:
14188       _codec ("Run-length encoding");
14189       caps = gst_caps_new_simple ("video/x-rle",
14190           "layout", G_TYPE_STRING, "quicktime", NULL);
14191       break;
14192     case FOURCC_WRLE:
14193       _codec ("Run-length encoding");
14194       caps = gst_caps_new_simple ("video/x-rle",
14195           "layout", G_TYPE_STRING, "microsoft", NULL);
14196       break;
14197     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14198     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14199       _codec ("Indeo Video 3");
14200       caps = gst_caps_new_simple ("video/x-indeo",
14201           "indeoversion", G_TYPE_INT, 3, NULL);
14202       break;
14203     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14204     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14205       _codec ("Intel Video 4");
14206       caps = gst_caps_new_simple ("video/x-indeo",
14207           "indeoversion", G_TYPE_INT, 4, NULL);
14208       break;
14209     case FOURCC_dvcp:
14210     case FOURCC_dvc_:
14211     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14212     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14213     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14214     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14215     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14216     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14217       _codec ("DV Video");
14218       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14219           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14220       break;
14221     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14222     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14223       _codec ("DVCPro50 Video");
14224       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14225           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14226       break;
14227     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14228     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14229       _codec ("DVCProHD Video");
14230       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14231           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14232       break;
14233     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14234       _codec ("Apple Graphics (SMC)");
14235       caps = gst_caps_new_empty_simple ("video/x-smc");
14236       break;
14237     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14238       _codec ("VP3");
14239       caps = gst_caps_new_empty_simple ("video/x-vp3");
14240       break;
14241     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14242       _codec ("VP6 Flash");
14243       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14244       break;
14245     case FOURCC_XiTh:
14246       _codec ("Theora");
14247       caps = gst_caps_new_empty_simple ("video/x-theora");
14248       /* theora uses one byte of padding in the data stream because it does not
14249        * allow 0 sized packets while theora does */
14250       entry->padding = 1;
14251       break;
14252     case FOURCC_drac:
14253       _codec ("Dirac");
14254       caps = gst_caps_new_empty_simple ("video/x-dirac");
14255       break;
14256     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14257       _codec ("TIFF still images");
14258       caps = gst_caps_new_empty_simple ("image/tiff");
14259       break;
14260     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14261       _codec ("Apple Intermediate Codec");
14262       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14263       break;
14264     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14265       _codec ("AVID DNxHD");
14266       caps = gst_caps_from_string ("video/x-dnxhd");
14267       break;
14268     case FOURCC_VP80:
14269     case FOURCC_vp08:
14270       _codec ("On2 VP8");
14271       caps = gst_caps_from_string ("video/x-vp8");
14272       break;
14273     case FOURCC_vp09:
14274       _codec ("Google VP9");
14275       caps = gst_caps_from_string ("video/x-vp9");
14276       break;
14277     case FOURCC_apcs:
14278       _codec ("Apple ProRes LT");
14279       caps =
14280           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14281           NULL);
14282       break;
14283     case FOURCC_apch:
14284       _codec ("Apple ProRes HQ");
14285       caps =
14286           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14287           NULL);
14288       break;
14289     case FOURCC_apcn:
14290       _codec ("Apple ProRes");
14291       caps =
14292           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14293           "standard", NULL);
14294       break;
14295     case FOURCC_apco:
14296       _codec ("Apple ProRes Proxy");
14297       caps =
14298           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14299           "proxy", NULL);
14300       break;
14301     case FOURCC_ap4h:
14302       _codec ("Apple ProRes 4444");
14303       caps =
14304           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14305           "4444", NULL);
14306       break;
14307     case FOURCC_ap4x:
14308       _codec ("Apple ProRes 4444 XQ");
14309       caps =
14310           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14311           "4444xq", NULL);
14312       break;
14313     case FOURCC_cfhd:
14314       _codec ("GoPro CineForm");
14315       caps = gst_caps_from_string ("video/x-cineform");
14316       break;
14317     case FOURCC_vc_1:
14318     case FOURCC_ovc1:
14319       _codec ("VC-1");
14320       caps = gst_caps_new_simple ("video/x-wmv",
14321           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14322       break;
14323     case FOURCC_av01:
14324       _codec ("AV1");
14325       caps = gst_caps_new_empty_simple ("video/x-av1");
14326       break;
14327     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14328     default:
14329     {
14330       caps = _get_unknown_codec_name ("video", fourcc);
14331       break;
14332     }
14333   }
14334
14335   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14336     GstVideoInfo info;
14337
14338     gst_video_info_init (&info);
14339     gst_video_info_set_format (&info, format, entry->width, entry->height);
14340
14341     caps = gst_video_info_to_caps (&info);
14342     *codec_name = gst_pb_utils_get_codec_description (caps);
14343
14344     /* enable clipping for raw video streams */
14345     stream->need_clip = TRUE;
14346     stream->alignment = 32;
14347   }
14348
14349   return caps;
14350 }
14351
14352 static guint
14353 round_up_pow2 (guint n)
14354 {
14355   n = n - 1;
14356   n = n | (n >> 1);
14357   n = n | (n >> 2);
14358   n = n | (n >> 4);
14359   n = n | (n >> 8);
14360   n = n | (n >> 16);
14361   return n + 1;
14362 }
14363
14364 static GstCaps *
14365 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14366     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14367     int len, gchar ** codec_name)
14368 {
14369   GstCaps *caps;
14370   const GstStructure *s;
14371   const gchar *name;
14372   gint endian = 0;
14373   GstAudioFormat format = 0;
14374   gint depth;
14375
14376   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14377
14378   depth = entry->bytes_per_packet * 8;
14379
14380   switch (fourcc) {
14381     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14382     case FOURCC_raw_:
14383       /* 8-bit audio is unsigned */
14384       if (depth == 8)
14385         format = GST_AUDIO_FORMAT_U8;
14386       /* otherwise it's signed and big-endian just like 'twos' */
14387     case FOURCC_twos:
14388       endian = G_BIG_ENDIAN;
14389       /* fall-through */
14390     case FOURCC_sowt:
14391     {
14392       gchar *str;
14393
14394       if (!endian)
14395         endian = G_LITTLE_ENDIAN;
14396
14397       if (!format)
14398         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14399
14400       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14401       _codec (str);
14402       g_free (str);
14403
14404       caps = gst_caps_new_simple ("audio/x-raw",
14405           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14406           "layout", G_TYPE_STRING, "interleaved", NULL);
14407       stream->alignment = GST_ROUND_UP_8 (depth);
14408       stream->alignment = round_up_pow2 (stream->alignment);
14409       break;
14410     }
14411     case FOURCC_fl64:
14412       _codec ("Raw 64-bit floating-point audio");
14413       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14414        * endian later */
14415       caps = gst_caps_new_simple ("audio/x-raw",
14416           "format", G_TYPE_STRING, "F64BE",
14417           "layout", G_TYPE_STRING, "interleaved", NULL);
14418       stream->alignment = 8;
14419       break;
14420     case FOURCC_fl32:
14421       _codec ("Raw 32-bit floating-point audio");
14422       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14423        * endian later */
14424       caps = gst_caps_new_simple ("audio/x-raw",
14425           "format", G_TYPE_STRING, "F32BE",
14426           "layout", G_TYPE_STRING, "interleaved", NULL);
14427       stream->alignment = 4;
14428       break;
14429     case FOURCC_in24:
14430       _codec ("Raw 24-bit PCM audio");
14431       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14432        * endian later */
14433       caps = gst_caps_new_simple ("audio/x-raw",
14434           "format", G_TYPE_STRING, "S24BE",
14435           "layout", G_TYPE_STRING, "interleaved", NULL);
14436       stream->alignment = 4;
14437       break;
14438     case FOURCC_in32:
14439       _codec ("Raw 32-bit PCM audio");
14440       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14441        * endian later */
14442       caps = gst_caps_new_simple ("audio/x-raw",
14443           "format", G_TYPE_STRING, "S32BE",
14444           "layout", G_TYPE_STRING, "interleaved", NULL);
14445       stream->alignment = 4;
14446       break;
14447     case FOURCC_s16l:
14448       _codec ("Raw 16-bit PCM audio");
14449       caps = gst_caps_new_simple ("audio/x-raw",
14450           "format", G_TYPE_STRING, "S16LE",
14451           "layout", G_TYPE_STRING, "interleaved", NULL);
14452       stream->alignment = 2;
14453       break;
14454     case FOURCC_ulaw:
14455       _codec ("Mu-law audio");
14456       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14457       break;
14458     case FOURCC_alaw:
14459       _codec ("A-law audio");
14460       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14461       break;
14462     case 0x0200736d:
14463     case 0x6d730002:
14464       _codec ("Microsoft ADPCM");
14465       /* Microsoft ADPCM-ACM code 2 */
14466       caps = gst_caps_new_simple ("audio/x-adpcm",
14467           "layout", G_TYPE_STRING, "microsoft", NULL);
14468       break;
14469     case 0x1100736d:
14470     case 0x6d730011:
14471       _codec ("DVI/IMA ADPCM");
14472       caps = gst_caps_new_simple ("audio/x-adpcm",
14473           "layout", G_TYPE_STRING, "dvi", NULL);
14474       break;
14475     case 0x1700736d:
14476     case 0x6d730017:
14477       _codec ("DVI/Intel IMA ADPCM");
14478       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14479       caps = gst_caps_new_simple ("audio/x-adpcm",
14480           "layout", G_TYPE_STRING, "quicktime", NULL);
14481       break;
14482     case 0x5500736d:
14483     case 0x6d730055:
14484       /* MPEG layer 3, CBR only (pre QT4.1) */
14485     case FOURCC__mp3:
14486     case FOURCC_mp3_:
14487       _codec ("MPEG-1 layer 3");
14488       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14489       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14490           "mpegversion", G_TYPE_INT, 1, NULL);
14491       break;
14492     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14493       _codec ("MPEG-1 layer 2");
14494       /* MPEG layer 2 */
14495       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14496           "mpegversion", G_TYPE_INT, 1, NULL);
14497       break;
14498     case 0x20736d:
14499     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14500       _codec ("EAC-3 audio");
14501       caps = gst_caps_new_simple ("audio/x-eac3",
14502           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14503       entry->sampled = TRUE;
14504       break;
14505     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14506     case FOURCC_ac_3:
14507       _codec ("AC-3 audio");
14508       caps = gst_caps_new_simple ("audio/x-ac3",
14509           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14510       entry->sampled = TRUE;
14511       break;
14512     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14513     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14514       _codec ("DTS audio");
14515       caps = gst_caps_new_simple ("audio/x-dts",
14516           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14517       entry->sampled = TRUE;
14518       break;
14519     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14520     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14521       _codec ("DTS-HD audio");
14522       caps = gst_caps_new_simple ("audio/x-dts",
14523           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14524       entry->sampled = TRUE;
14525       break;
14526     case FOURCC_MAC3:
14527       _codec ("MACE-3");
14528       caps = gst_caps_new_simple ("audio/x-mace",
14529           "maceversion", G_TYPE_INT, 3, NULL);
14530       break;
14531     case FOURCC_MAC6:
14532       _codec ("MACE-6");
14533       caps = gst_caps_new_simple ("audio/x-mace",
14534           "maceversion", G_TYPE_INT, 6, NULL);
14535       break;
14536     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14537       /* ogg/vorbis */
14538       caps = gst_caps_new_empty_simple ("application/ogg");
14539       break;
14540     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14541       _codec ("DV audio");
14542       caps = gst_caps_new_empty_simple ("audio/x-dv");
14543       break;
14544     case FOURCC_mp4a:
14545       _codec ("MPEG-4 AAC audio");
14546       caps = gst_caps_new_simple ("audio/mpeg",
14547           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14548           "stream-format", G_TYPE_STRING, "raw", NULL);
14549       break;
14550     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14551       _codec ("QDesign Music");
14552       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14553       break;
14554     case FOURCC_QDM2:
14555       _codec ("QDesign Music v.2");
14556       /* FIXME: QDesign music version 2 (no constant) */
14557       if (FALSE && data) {
14558         caps = gst_caps_new_simple ("audio/x-qdm2",
14559             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14560             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14561             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14562       } else {
14563         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14564       }
14565       break;
14566     case FOURCC_agsm:
14567       _codec ("GSM audio");
14568       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14569       break;
14570     case FOURCC_samr:
14571       _codec ("AMR audio");
14572       caps = gst_caps_new_empty_simple ("audio/AMR");
14573       break;
14574     case FOURCC_sawb:
14575       _codec ("AMR-WB audio");
14576       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14577       break;
14578     case FOURCC_ima4:
14579       _codec ("Quicktime IMA ADPCM");
14580       caps = gst_caps_new_simple ("audio/x-adpcm",
14581           "layout", G_TYPE_STRING, "quicktime", NULL);
14582       break;
14583     case FOURCC_alac:
14584       _codec ("Apple lossless audio");
14585       caps = gst_caps_new_empty_simple ("audio/x-alac");
14586       break;
14587     case FOURCC_fLaC:
14588       _codec ("Free Lossless Audio Codec");
14589       caps = gst_caps_new_simple ("audio/x-flac",
14590           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14591       break;
14592     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14593       _codec ("QualComm PureVoice");
14594       caps = gst_caps_from_string ("audio/qcelp");
14595       break;
14596     case FOURCC_wma_:
14597     case FOURCC_owma:
14598       _codec ("WMA");
14599       caps = gst_caps_new_empty_simple ("audio/x-wma");
14600       break;
14601     case FOURCC_opus:
14602       _codec ("Opus");
14603       caps = gst_caps_new_empty_simple ("audio/x-opus");
14604       break;
14605     case FOURCC_lpcm:
14606     {
14607       guint32 flags = 0;
14608       guint32 depth = 0;
14609       guint32 width = 0;
14610       GstAudioFormat format;
14611       enum
14612       {
14613         FLAG_IS_FLOAT = 0x1,
14614         FLAG_IS_BIG_ENDIAN = 0x2,
14615         FLAG_IS_SIGNED = 0x4,
14616         FLAG_IS_PACKED = 0x8,
14617         FLAG_IS_ALIGNED_HIGH = 0x10,
14618         FLAG_IS_NON_INTERLEAVED = 0x20
14619       };
14620       _codec ("Raw LPCM audio");
14621
14622       if (data && len >= 36) {
14623         depth = QT_UINT32 (data + 24);
14624         flags = QT_UINT32 (data + 28);
14625         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14626       }
14627       if ((flags & FLAG_IS_FLOAT) == 0) {
14628         if (depth == 0)
14629           depth = 16;
14630         if (width == 0)
14631           width = 16;
14632         if ((flags & FLAG_IS_ALIGNED_HIGH))
14633           depth = width;
14634
14635         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14636             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14637             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14638         caps = gst_caps_new_simple ("audio/x-raw",
14639             "format", G_TYPE_STRING,
14640             format !=
14641             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14642             "UNKNOWN", "layout", G_TYPE_STRING,
14643             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14644             "interleaved", NULL);
14645         stream->alignment = GST_ROUND_UP_8 (depth);
14646         stream->alignment = round_up_pow2 (stream->alignment);
14647       } else {
14648         if (width == 0)
14649           width = 32;
14650         if (width == 64) {
14651           if (flags & FLAG_IS_BIG_ENDIAN)
14652             format = GST_AUDIO_FORMAT_F64BE;
14653           else
14654             format = GST_AUDIO_FORMAT_F64LE;
14655         } else {
14656           if (flags & FLAG_IS_BIG_ENDIAN)
14657             format = GST_AUDIO_FORMAT_F32BE;
14658           else
14659             format = GST_AUDIO_FORMAT_F32LE;
14660         }
14661         caps = gst_caps_new_simple ("audio/x-raw",
14662             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14663             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14664             "non-interleaved" : "interleaved", NULL);
14665         stream->alignment = width / 8;
14666       }
14667       break;
14668     }
14669     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14670     {
14671       _codec ("AC4");
14672       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14673       break;
14674     }
14675     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14676       /* ? */
14677     default:
14678     {
14679       caps = _get_unknown_codec_name ("audio", fourcc);
14680       break;
14681     }
14682   }
14683
14684   if (caps) {
14685     GstCaps *templ_caps =
14686         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14687     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14688     gst_caps_unref (caps);
14689     gst_caps_unref (templ_caps);
14690     caps = intersection;
14691   }
14692
14693   /* enable clipping for raw audio streams */
14694   s = gst_caps_get_structure (caps, 0);
14695   name = gst_structure_get_name (s);
14696   if (g_str_has_prefix (name, "audio/x-raw")) {
14697     stream->need_clip = TRUE;
14698     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
14699     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14700     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
14701         stream->max_buffer_size);
14702   }
14703   return caps;
14704 }
14705
14706 static GstCaps *
14707 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14708     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14709     const guint8 * stsd_entry_data, gchar ** codec_name)
14710 {
14711   GstCaps *caps;
14712
14713   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14714
14715   switch (fourcc) {
14716     case FOURCC_mp4s:
14717       _codec ("DVD subtitle");
14718       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14719       stream->need_process = TRUE;
14720       break;
14721     case FOURCC_text:
14722       _codec ("Quicktime timed text");
14723       goto text;
14724     case FOURCC_tx3g:
14725       _codec ("3GPP timed text");
14726     text:
14727       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14728           "utf8", NULL);
14729       /* actual text piece needs to be extracted */
14730       stream->need_process = TRUE;
14731       break;
14732     case FOURCC_stpp:
14733       _codec ("XML subtitles");
14734       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14735       break;
14736     case FOURCC_c608:
14737       _codec ("CEA 608 Closed Caption");
14738       caps =
14739           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
14740           G_TYPE_STRING, "s334-1a", NULL);
14741       stream->need_process = TRUE;
14742       stream->need_split = TRUE;
14743       break;
14744     case FOURCC_c708:
14745       _codec ("CEA 708 Closed Caption");
14746       caps =
14747           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
14748           G_TYPE_STRING, "cdp", NULL);
14749       stream->need_process = TRUE;
14750       break;
14751
14752     default:
14753     {
14754       caps = _get_unknown_codec_name ("text", fourcc);
14755       break;
14756     }
14757   }
14758   return caps;
14759 }
14760
14761 static GstCaps *
14762 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14763     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14764     const guint8 * stsd_entry_data, gchar ** codec_name)
14765 {
14766   GstCaps *caps;
14767
14768   switch (fourcc) {
14769     case FOURCC_m1v:
14770       _codec ("MPEG 1 video");
14771       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14772           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14773       break;
14774     default:
14775       caps = NULL;
14776       break;
14777   }
14778   return caps;
14779 }
14780
14781 static void
14782 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14783     const gchar * system_id)
14784 {
14785   gint i;
14786
14787   if (!qtdemux->protection_system_ids)
14788     qtdemux->protection_system_ids =
14789         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14790   /* Check whether we already have an entry for this system ID. */
14791   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14792     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14793     if (g_ascii_strcasecmp (system_id, id) == 0) {
14794       return;
14795     }
14796   }
14797   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14798   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14799           -1));
14800 }