qtdemux: fix crashes when input stream contained no stsd entries
[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   if (stream->stsd_entries_length == 0)
10658     goto corrupt_file;
10659   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10660   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10661   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10662
10663   stsd_entry_data = stsd_data + 16;
10664   remaining_stsd_len = stsd_len - 16;
10665   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10666     guint32 fourcc;
10667     gchar *codec = NULL;
10668     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10669
10670     /* and that entry should fit within stsd */
10671     len = QT_UINT32 (stsd_entry_data);
10672     if (len > remaining_stsd_len)
10673       goto corrupt_file;
10674
10675     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10676     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10677         GST_FOURCC_ARGS (entry->fourcc));
10678     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10679
10680     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10681       goto error_encrypted;
10682
10683     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10684       /* FIXME this looks wrong, there might be multiple children
10685        * with the same type */
10686       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10687       stream->protected = TRUE;
10688       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10689         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10690     }
10691
10692     if (stream->subtype == FOURCC_vide) {
10693       GNode *colr;
10694       GNode *fiel;
10695       GNode *pasp;
10696       gboolean gray;
10697       gint depth, palette_size, palette_count;
10698       guint32 *palette_data = NULL;
10699
10700       entry->sampled = TRUE;
10701
10702       stream->display_width = w >> 16;
10703       stream->display_height = h >> 16;
10704
10705       offset = 16;
10706       if (len < 86)             /* TODO verify */
10707         goto corrupt_file;
10708
10709       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10710       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10711       entry->fps_n = 0;         /* this is filled in later */
10712       entry->fps_d = 0;         /* this is filled in later */
10713       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10714       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10715
10716       /* if color_table_id is 0, ctab atom must follow; however some files
10717        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10718        * if color table is not present we'll correct the value */
10719       if (entry->color_table_id == 0 &&
10720           (len < 90
10721               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10722         entry->color_table_id = -1;
10723       }
10724
10725       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10726           entry->width, entry->height, entry->bits_per_sample,
10727           entry->color_table_id);
10728
10729       depth = entry->bits_per_sample;
10730
10731       /* more than 32 bits means grayscale */
10732       gray = (depth > 32);
10733       /* low 32 bits specify the depth  */
10734       depth &= 0x1F;
10735
10736       /* different number of palette entries is determined by depth. */
10737       palette_count = 0;
10738       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10739         palette_count = (1 << depth);
10740       palette_size = palette_count * 4;
10741
10742       if (entry->color_table_id) {
10743         switch (palette_count) {
10744           case 0:
10745             break;
10746           case 2:
10747             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10748             break;
10749           case 4:
10750             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10751             break;
10752           case 16:
10753             if (gray)
10754               palette_data =
10755                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10756             else
10757               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10758             break;
10759           case 256:
10760             if (gray)
10761               palette_data =
10762                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10763             else
10764               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10765             break;
10766           default:
10767             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10768                 (_("The video in this file might not play correctly.")),
10769                 ("unsupported palette depth %d", depth));
10770             break;
10771         }
10772       } else {
10773         gint i, j, start, end;
10774
10775         if (len < 94)
10776           goto corrupt_file;
10777
10778         /* read table */
10779         start = QT_UINT32 (stsd_entry_data + offset + 70);
10780         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10781         end = QT_UINT16 (stsd_entry_data + offset + 76);
10782
10783         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10784             start, end, palette_count);
10785
10786         if (end > 255)
10787           end = 255;
10788         if (start > end)
10789           start = end;
10790
10791         if (len < 94 + (end - start) * 8)
10792           goto corrupt_file;
10793
10794         /* palette is always the same size */
10795         palette_data = g_malloc0 (256 * 4);
10796         palette_size = 256 * 4;
10797
10798         for (j = 0, i = start; i <= end; j++, i++) {
10799           guint32 a, r, g, b;
10800
10801           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10802           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10803           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10804           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10805
10806           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10807               (g & 0xff00) | (b >> 8);
10808         }
10809       }
10810
10811       if (entry->caps)
10812         gst_caps_unref (entry->caps);
10813
10814       entry->caps =
10815           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10816           &codec);
10817       if (G_UNLIKELY (!entry->caps)) {
10818         g_free (palette_data);
10819         goto unknown_stream;
10820       }
10821
10822       if (codec) {
10823         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10824             GST_TAG_VIDEO_CODEC, codec, NULL);
10825         g_free (codec);
10826         codec = NULL;
10827       }
10828
10829       if (palette_data) {
10830         GstStructure *s;
10831
10832         if (entry->rgb8_palette)
10833           gst_memory_unref (entry->rgb8_palette);
10834         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10835             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10836
10837         s = gst_caps_get_structure (entry->caps, 0);
10838
10839         /* non-raw video has a palette_data property. raw video has the palette as
10840          * an extra plane that we append to the output buffers before we push
10841          * them*/
10842         if (!gst_structure_has_name (s, "video/x-raw")) {
10843           GstBuffer *palette;
10844
10845           palette = gst_buffer_new ();
10846           gst_buffer_append_memory (palette, entry->rgb8_palette);
10847           entry->rgb8_palette = NULL;
10848
10849           gst_caps_set_simple (entry->caps, "palette_data",
10850               GST_TYPE_BUFFER, palette, NULL);
10851           gst_buffer_unref (palette);
10852         }
10853       } else if (palette_count != 0) {
10854         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10855             (NULL), ("Unsupported palette depth %d", depth));
10856       }
10857
10858       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10859           QT_UINT16 (stsd_entry_data + offset + 32));
10860
10861       esds = NULL;
10862       pasp = NULL;
10863       colr = NULL;
10864       fiel = NULL;
10865       /* pick 'the' stsd child */
10866       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10867       // We should skip parsing the stsd for non-protected streams if
10868       // the entry doesn't match the fourcc, since they don't change
10869       // format. However, for protected streams we can have partial
10870       // encryption, where parts of the stream are encrypted and parts
10871       // not. For both parts of such streams, we should ensure the
10872       // esds overrides are parsed for both from the stsd.
10873       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10874         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
10875           mp4v = NULL;
10876         else if (!stream->protected)
10877           mp4v = NULL;
10878       }
10879
10880       if (mp4v) {
10881         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10882         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10883         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10884         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10885       }
10886
10887       if (pasp) {
10888         const guint8 *pasp_data = (const guint8 *) pasp->data;
10889         gint len = QT_UINT32 (pasp_data);
10890
10891         if (len == 16) {
10892           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10893           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10894         } else {
10895           CUR_STREAM (stream)->par_w = 0;
10896           CUR_STREAM (stream)->par_h = 0;
10897         }
10898       } else {
10899         CUR_STREAM (stream)->par_w = 0;
10900         CUR_STREAM (stream)->par_h = 0;
10901       }
10902
10903       if (fiel) {
10904         const guint8 *fiel_data = (const guint8 *) fiel->data;
10905         gint len = QT_UINT32 (fiel_data);
10906
10907         if (len == 10) {
10908           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10909           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10910         }
10911       }
10912
10913       if (colr) {
10914         const guint8 *colr_data = (const guint8 *) colr->data;
10915         gint len = QT_UINT32 (colr_data);
10916
10917         if (len == 19 || len == 18) {
10918           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10919
10920           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10921             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10922             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10923             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10924             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10925
10926             CUR_STREAM (stream)->colorimetry.primaries =
10927                 gst_video_color_primaries_from_iso (primaries);
10928             CUR_STREAM (stream)->colorimetry.transfer =
10929                 gst_video_color_transfer_from_iso (transfer_function);
10930             CUR_STREAM (stream)->colorimetry.matrix =
10931                 gst_video_color_matrix_from_iso (matrix);
10932             CUR_STREAM (stream)->colorimetry.range =
10933                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10934                 GST_VIDEO_COLOR_RANGE_16_235;
10935           } else {
10936             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10937           }
10938         } else {
10939           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10940         }
10941       }
10942
10943       if (esds) {
10944         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10945             stream->stream_tags);
10946       } else {
10947         switch (fourcc) {
10948           case FOURCC_H264:
10949           case FOURCC_avc1:
10950           case FOURCC_avc3:
10951           {
10952             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10953             const guint8 *avc_data = stsd_entry_data + 0x56;
10954
10955             /* find avcC */
10956             while (len >= 0x8) {
10957               gint size;
10958
10959               if (QT_UINT32 (avc_data) <= len)
10960                 size = QT_UINT32 (avc_data) - 0x8;
10961               else
10962                 size = len - 0x8;
10963
10964               if (size < 1)
10965                 /* No real data, so break out */
10966                 break;
10967
10968               switch (QT_FOURCC (avc_data + 0x4)) {
10969                 case FOURCC_avcC:
10970                 {
10971                   /* parse, if found */
10972                   GstBuffer *buf;
10973
10974                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10975
10976                   /* First 4 bytes are the length of the atom, the next 4 bytes
10977                    * are the fourcc, the next 1 byte is the version, and the
10978                    * subsequent bytes are profile_tier_level structure like data. */
10979                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10980                       avc_data + 8 + 1, size - 1);
10981                   buf = gst_buffer_new_and_alloc (size);
10982                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10983                   gst_caps_set_simple (entry->caps,
10984                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10985                   gst_buffer_unref (buf);
10986
10987                   break;
10988                 }
10989                 case FOURCC_strf:
10990                 {
10991                   GstBuffer *buf;
10992
10993                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10994
10995                   /* First 4 bytes are the length of the atom, the next 4 bytes
10996                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10997                    * next 1 byte is the version, and the
10998                    * subsequent bytes are sequence parameter set like data. */
10999
11000                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11001                   if (size > 1) {
11002                     gst_codec_utils_h264_caps_set_level_and_profile
11003                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11004
11005                     buf = gst_buffer_new_and_alloc (size);
11006                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11007                     gst_caps_set_simple (entry->caps,
11008                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11009                     gst_buffer_unref (buf);
11010                   }
11011                   break;
11012                 }
11013                 case FOURCC_btrt:
11014                 {
11015                   guint avg_bitrate, max_bitrate;
11016
11017                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11018                   if (size < 12)
11019                     break;
11020
11021                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11022                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11023
11024                   if (!max_bitrate && !avg_bitrate)
11025                     break;
11026
11027                   /* Some muxers seem to swap the average and maximum bitrates
11028                    * (I'm looking at you, YouTube), so we swap for sanity. */
11029                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11030                     guint temp = avg_bitrate;
11031
11032                     avg_bitrate = max_bitrate;
11033                     max_bitrate = temp;
11034                   }
11035
11036                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11037                     gst_tag_list_add (stream->stream_tags,
11038                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11039                         max_bitrate, NULL);
11040                   }
11041                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11042                     gst_tag_list_add (stream->stream_tags,
11043                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11044                         NULL);
11045                   }
11046
11047                   break;
11048                 }
11049
11050                 default:
11051                   break;
11052               }
11053
11054               len -= size + 8;
11055               avc_data += size + 8;
11056             }
11057
11058             break;
11059           }
11060           case FOURCC_H265:
11061           case FOURCC_hvc1:
11062           case FOURCC_hev1:
11063           {
11064             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11065             const guint8 *hevc_data = stsd_entry_data + 0x56;
11066
11067             /* find hevc */
11068             while (len >= 0x8) {
11069               gint size;
11070
11071               if (QT_UINT32 (hevc_data) <= len)
11072                 size = QT_UINT32 (hevc_data) - 0x8;
11073               else
11074                 size = len - 0x8;
11075
11076               if (size < 1)
11077                 /* No real data, so break out */
11078                 break;
11079
11080               switch (QT_FOURCC (hevc_data + 0x4)) {
11081                 case FOURCC_hvcC:
11082                 {
11083                   /* parse, if found */
11084                   GstBuffer *buf;
11085
11086                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11087
11088                   /* First 4 bytes are the length of the atom, the next 4 bytes
11089                    * are the fourcc, the next 1 byte is the version, and the
11090                    * subsequent bytes are sequence parameter set like data. */
11091                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11092                       (entry->caps, hevc_data + 8 + 1, size - 1);
11093
11094                   buf = gst_buffer_new_and_alloc (size);
11095                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11096                   gst_caps_set_simple (entry->caps,
11097                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11098                   gst_buffer_unref (buf);
11099                   break;
11100                 }
11101                 default:
11102                   break;
11103               }
11104               len -= size + 8;
11105               hevc_data += size + 8;
11106             }
11107             break;
11108           }
11109           case FOURCC_mp4v:
11110           case FOURCC_MP4V:
11111           case FOURCC_fmp4:
11112           case FOURCC_FMP4:
11113           case FOURCC_xvid:
11114           case FOURCC_XVID:
11115           {
11116             GNode *glbl;
11117
11118             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11119                 GST_FOURCC_ARGS (fourcc));
11120
11121             /* codec data might be in glbl extension atom */
11122             glbl = mp4v ?
11123                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11124             if (glbl) {
11125               guint8 *data;
11126               GstBuffer *buf;
11127               gint len;
11128
11129               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11130               data = glbl->data;
11131               len = QT_UINT32 (data);
11132               if (len > 0x8) {
11133                 len -= 0x8;
11134                 buf = gst_buffer_new_and_alloc (len);
11135                 gst_buffer_fill (buf, 0, data + 8, len);
11136                 gst_caps_set_simple (entry->caps,
11137                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11138                 gst_buffer_unref (buf);
11139               }
11140             }
11141             break;
11142           }
11143           case FOURCC_mjp2:
11144           {
11145             /* see annex I of the jpeg2000 spec */
11146             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11147             const guint8 *data;
11148             const gchar *colorspace = NULL;
11149             gint ncomp = 0;
11150             guint32 ncomp_map = 0;
11151             gint32 *comp_map = NULL;
11152             guint32 nchan_def = 0;
11153             gint32 *chan_def = NULL;
11154
11155             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11156             /* some required atoms */
11157             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11158             if (!mjp2)
11159               break;
11160             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11161             if (!jp2h)
11162               break;
11163
11164             /* number of components; redundant with info in codestream, but useful
11165                to a muxer */
11166             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11167             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11168               break;
11169             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11170
11171             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11172             if (!colr)
11173               break;
11174             GST_DEBUG_OBJECT (qtdemux, "found colr");
11175             /* extract colour space info */
11176             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11177               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11178                 case 16:
11179                   colorspace = "sRGB";
11180                   break;
11181                 case 17:
11182                   colorspace = "GRAY";
11183                   break;
11184                 case 18:
11185                   colorspace = "sYUV";
11186                   break;
11187                 default:
11188                   colorspace = NULL;
11189                   break;
11190               }
11191             }
11192             if (!colorspace)
11193               /* colr is required, and only values 16, 17, and 18 are specified,
11194                  so error if we have no colorspace */
11195               break;
11196
11197             /* extract component mapping */
11198             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11199             if (cmap) {
11200               guint32 cmap_len = 0;
11201               int i;
11202               cmap_len = QT_UINT32 (cmap->data);
11203               if (cmap_len >= 8) {
11204                 /* normal box, subtract off header */
11205                 cmap_len -= 8;
11206                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11207                 if (cmap_len % 4 == 0) {
11208                   ncomp_map = (cmap_len / 4);
11209                   comp_map = g_new0 (gint32, ncomp_map);
11210                   for (i = 0; i < ncomp_map; i++) {
11211                     guint16 cmp;
11212                     guint8 mtyp, pcol;
11213                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11214                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11215                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11216                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11217                   }
11218                 }
11219               }
11220             }
11221             /* extract channel definitions */
11222             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11223             if (cdef) {
11224               guint32 cdef_len = 0;
11225               int i;
11226               cdef_len = QT_UINT32 (cdef->data);
11227               if (cdef_len >= 10) {
11228                 /* normal box, subtract off header and len */
11229                 cdef_len -= 10;
11230                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11231                 if (cdef_len % 6 == 0) {
11232                   nchan_def = (cdef_len / 6);
11233                   chan_def = g_new0 (gint32, nchan_def);
11234                   for (i = 0; i < nchan_def; i++)
11235                     chan_def[i] = -1;
11236                   for (i = 0; i < nchan_def; i++) {
11237                     guint16 cn, typ, asoc;
11238                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11239                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11240                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11241                     if (cn < nchan_def) {
11242                       switch (typ) {
11243                         case 0:
11244                           chan_def[cn] = asoc;
11245                           break;
11246                         case 1:
11247                           chan_def[cn] = 0;     /* alpha */
11248                           break;
11249                         default:
11250                           chan_def[cn] = -typ;
11251                       }
11252                     }
11253                   }
11254                 }
11255               }
11256             }
11257
11258             gst_caps_set_simple (entry->caps,
11259                 "num-components", G_TYPE_INT, ncomp, NULL);
11260             gst_caps_set_simple (entry->caps,
11261                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11262
11263             if (comp_map) {
11264               GValue arr = { 0, };
11265               GValue elt = { 0, };
11266               int i;
11267               g_value_init (&arr, GST_TYPE_ARRAY);
11268               g_value_init (&elt, G_TYPE_INT);
11269               for (i = 0; i < ncomp_map; i++) {
11270                 g_value_set_int (&elt, comp_map[i]);
11271                 gst_value_array_append_value (&arr, &elt);
11272               }
11273               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11274                   "component-map", &arr);
11275               g_value_unset (&elt);
11276               g_value_unset (&arr);
11277               g_free (comp_map);
11278             }
11279
11280             if (chan_def) {
11281               GValue arr = { 0, };
11282               GValue elt = { 0, };
11283               int i;
11284               g_value_init (&arr, GST_TYPE_ARRAY);
11285               g_value_init (&elt, G_TYPE_INT);
11286               for (i = 0; i < nchan_def; i++) {
11287                 g_value_set_int (&elt, chan_def[i]);
11288                 gst_value_array_append_value (&arr, &elt);
11289               }
11290               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11291                   "channel-definitions", &arr);
11292               g_value_unset (&elt);
11293               g_value_unset (&arr);
11294               g_free (chan_def);
11295             }
11296
11297             /* some optional atoms */
11298             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11299             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11300
11301             /* indicate possible fields in caps */
11302             if (field) {
11303               data = (guint8 *) field->data + 8;
11304               if (*data != 1)
11305                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11306                     (gint) * data, NULL);
11307             }
11308             /* add codec_data if provided */
11309             if (prefix) {
11310               GstBuffer *buf;
11311               gint len;
11312
11313               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11314               data = prefix->data;
11315               len = QT_UINT32 (data);
11316               if (len > 0x8) {
11317                 len -= 0x8;
11318                 buf = gst_buffer_new_and_alloc (len);
11319                 gst_buffer_fill (buf, 0, data + 8, len);
11320                 gst_caps_set_simple (entry->caps,
11321                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11322                 gst_buffer_unref (buf);
11323               }
11324             }
11325             break;
11326           }
11327           case FOURCC_SVQ3:
11328           case FOURCC_VP31:
11329           {
11330             GstBuffer *buf;
11331             GstBuffer *seqh = NULL;
11332             const guint8 *gamma_data = NULL;
11333             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11334
11335             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11336                 &seqh);
11337             if (gamma_data) {
11338               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11339                   QT_FP32 (gamma_data), NULL);
11340             }
11341             if (seqh) {
11342               /* sorry for the bad name, but we don't know what this is, other
11343                * than its own fourcc */
11344               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11345                   NULL);
11346               gst_buffer_unref (seqh);
11347             }
11348
11349             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11350             buf = gst_buffer_new_and_alloc (len);
11351             gst_buffer_fill (buf, 0, stsd_data, len);
11352             gst_caps_set_simple (entry->caps,
11353                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11354             gst_buffer_unref (buf);
11355             break;
11356           }
11357           case FOURCC_jpeg:
11358           {
11359             /* https://developer.apple.com/standards/qtff-2001.pdf,
11360              * page 92, "Video Sample Description", under table 3.1 */
11361             GstByteReader br;
11362
11363             const gint compressor_offset =
11364                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11365             const gint min_size = compressor_offset + 32 + 2 + 2;
11366             GNode *jpeg;
11367             guint32 len;
11368             guint16 color_table_id = 0;
11369             gboolean ok;
11370
11371             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11372
11373             /* recover information on interlaced/progressive */
11374             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11375             if (!jpeg)
11376               break;
11377
11378             len = QT_UINT32 (jpeg->data);
11379             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11380                 min_size);
11381             if (len >= min_size) {
11382               gst_byte_reader_init (&br, jpeg->data, len);
11383
11384               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11385               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11386               if (color_table_id != 0) {
11387                 /* the spec says there can be concatenated chunks in the data, and we want
11388                  * to find one called field. Walk through them. */
11389                 gint offset = min_size;
11390                 while (offset + 8 < len) {
11391                   guint32 size = 0, tag;
11392                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11393                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11394                   if (!ok || size < 8) {
11395                     GST_WARNING_OBJECT (qtdemux,
11396                         "Failed to walk optional chunk list");
11397                     break;
11398                   }
11399                   GST_DEBUG_OBJECT (qtdemux,
11400                       "Found optional %4.4s chunk, size %u",
11401                       (const char *) &tag, size);
11402                   if (tag == FOURCC_fiel) {
11403                     guint8 n_fields = 0, ordering = 0;
11404                     gst_byte_reader_get_uint8 (&br, &n_fields);
11405                     gst_byte_reader_get_uint8 (&br, &ordering);
11406                     if (n_fields == 1 || n_fields == 2) {
11407                       GST_DEBUG_OBJECT (qtdemux,
11408                           "Found fiel tag with %u fields, ordering %u",
11409                           n_fields, ordering);
11410                       if (n_fields == 2)
11411                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11412                             "interlace-mode", G_TYPE_STRING, "interleaved",
11413                             NULL);
11414                     } else {
11415                       GST_WARNING_OBJECT (qtdemux,
11416                           "Found fiel tag with invalid fields (%u)", n_fields);
11417                     }
11418                   }
11419                   offset += size;
11420                 }
11421               } else {
11422                 GST_DEBUG_OBJECT (qtdemux,
11423                     "Color table ID is 0, not trying to get interlacedness");
11424               }
11425             } else {
11426               GST_WARNING_OBJECT (qtdemux,
11427                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11428             }
11429
11430             break;
11431           }
11432           case FOURCC_rle_:
11433           case FOURCC_WRLE:
11434           {
11435             gst_caps_set_simple (entry->caps,
11436                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11437                 NULL);
11438             break;
11439           }
11440           case FOURCC_XiTh:
11441           {
11442             GNode *xith, *xdxt;
11443
11444             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11445             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11446             if (!xith)
11447               break;
11448
11449             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11450             if (!xdxt)
11451               break;
11452
11453             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11454             /* collect the headers and store them in a stream list so that we can
11455              * send them out first */
11456             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11457             break;
11458           }
11459           case FOURCC_ovc1:
11460           {
11461             GNode *ovc1;
11462             guint8 *ovc1_data;
11463             guint ovc1_len;
11464             GstBuffer *buf;
11465
11466             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11467             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11468             if (!ovc1)
11469               break;
11470             ovc1_data = ovc1->data;
11471             ovc1_len = QT_UINT32 (ovc1_data);
11472             if (ovc1_len <= 198) {
11473               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11474               break;
11475             }
11476             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11477             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11478             gst_caps_set_simple (entry->caps,
11479                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11480             gst_buffer_unref (buf);
11481             break;
11482           }
11483           case FOURCC_vc_1:
11484           {
11485             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11486             const guint8 *vc1_data = stsd_entry_data + 0x56;
11487
11488             /* find dvc1 */
11489             while (len >= 8) {
11490               gint size;
11491
11492               if (QT_UINT32 (vc1_data) <= len)
11493                 size = QT_UINT32 (vc1_data) - 8;
11494               else
11495                 size = len - 8;
11496
11497               if (size < 1)
11498                 /* No real data, so break out */
11499                 break;
11500
11501               switch (QT_FOURCC (vc1_data + 0x4)) {
11502                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11503                 {
11504                   GstBuffer *buf;
11505
11506                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11507                   buf = gst_buffer_new_and_alloc (size);
11508                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11509                   gst_caps_set_simple (entry->caps,
11510                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11511                   gst_buffer_unref (buf);
11512                   break;
11513                 }
11514                 default:
11515                   break;
11516               }
11517               len -= size + 8;
11518               vc1_data += size + 8;
11519             }
11520             break;
11521           }
11522           case FOURCC_av01:
11523           {
11524             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11525             const guint8 *av1_data = stsd_entry_data + 0x56;
11526
11527             /* find av1C */
11528             while (len >= 0x8) {
11529               gint size;
11530
11531               if (QT_UINT32 (av1_data) <= len)
11532                 size = QT_UINT32 (av1_data) - 0x8;
11533               else
11534                 size = len - 0x8;
11535
11536               if (size < 1)
11537                 /* No real data, so break out */
11538                 break;
11539
11540               switch (QT_FOURCC (av1_data + 0x4)) {
11541                 case FOURCC_av1C:
11542                 {
11543                   /* parse, if found */
11544                   GstBuffer *buf;
11545                   guint8 pres_delay_field;
11546
11547                   GST_DEBUG_OBJECT (qtdemux,
11548                       "found av1C codec_data in stsd of size %d", size);
11549
11550                   /* not enough data, just ignore and hope for the best */
11551                   if (size < 5)
11552                     break;
11553
11554                   /* Content is:
11555                    * 4 bytes: atom length
11556                    * 4 bytes: fourcc
11557                    * 1 byte: version
11558                    * 3 bytes: flags
11559                    * 3 bits: reserved
11560                    * 1 bits:  initial_presentation_delay_present
11561                    * 4 bits: initial_presentation_delay (if present else reserved
11562                    * rest: OBUs.
11563                    */
11564
11565                   if (av1_data[9] != 0) {
11566                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11567                     break;
11568                   }
11569
11570                   /* We skip initial_presentation_delay* for now */
11571                   pres_delay_field = *(av1_data + 12);
11572                   if (pres_delay_field & (1 << 5)) {
11573                     gst_caps_set_simple (entry->caps,
11574                         "presentation-delay", G_TYPE_INT,
11575                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11576                   }
11577                   if (size > 5) {
11578                     buf = gst_buffer_new_and_alloc (size - 5);
11579                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11580                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11581                     gst_caps_set_simple (entry->caps,
11582                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11583                     gst_buffer_unref (buf);
11584                   }
11585                   break;
11586                 }
11587                 default:
11588                   break;
11589               }
11590
11591               len -= size + 8;
11592               av1_data += size + 8;
11593             }
11594
11595             break;
11596           }
11597
11598             /* TODO: Need to parse vpcC for VP8 codec too.
11599              * Note that VPCodecConfigurationBox (vpcC) is defined for
11600              * vp08, vp09, and vp10 fourcc. */
11601           case FOURCC_vp09:
11602           {
11603             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11604             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11605
11606             /* find vpcC */
11607             while (len >= 0x8) {
11608               gint size;
11609
11610               if (QT_UINT32 (vpcc_data) <= len)
11611                 size = QT_UINT32 (vpcc_data) - 0x8;
11612               else
11613                 size = len - 0x8;
11614
11615               if (size < 1)
11616                 /* No real data, so break out */
11617                 break;
11618
11619               switch (QT_FOURCC (vpcc_data + 0x4)) {
11620                 case FOURCC_vpcC:
11621                 {
11622                   const gchar *profile_str = NULL;
11623                   const gchar *chroma_format_str = NULL;
11624                   guint8 profile;
11625                   guint8 bitdepth;
11626                   guint8 chroma_format;
11627                   GstVideoColorimetry cinfo;
11628
11629                   /* parse, if found */
11630                   GST_DEBUG_OBJECT (qtdemux,
11631                       "found vp codec_data in stsd of size %d", size);
11632
11633                   /* the meaning of "size" is length of the atom body, excluding
11634                    * atom length and fourcc fields */
11635                   if (size < 12)
11636                     break;
11637
11638                   /* Content is:
11639                    * 4 bytes: atom length
11640                    * 4 bytes: fourcc
11641                    * 1 byte: version
11642                    * 3 bytes: flags
11643                    * 1 byte: profile
11644                    * 1 byte: level
11645                    * 4 bits: bitDepth
11646                    * 3 bits: chromaSubsampling
11647                    * 1 bit: videoFullRangeFlag
11648                    * 1 byte: colourPrimaries
11649                    * 1 byte: transferCharacteristics
11650                    * 1 byte: matrixCoefficients
11651                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11652                    * rest: codecIntializationData (not used for vp8 and vp9)
11653                    */
11654
11655                   if (vpcc_data[8] != 1) {
11656                     GST_WARNING_OBJECT (qtdemux,
11657                         "unknown vpcC version %d", vpcc_data[8]);
11658                     break;
11659                   }
11660
11661                   profile = vpcc_data[12];
11662                   switch (profile) {
11663                     case 0:
11664                       profile_str = "0";
11665                       break;
11666                     case 1:
11667                       profile_str = "1";
11668                       break;
11669                     case 2:
11670                       profile_str = "2";
11671                       break;
11672                     case 3:
11673                       profile_str = "3";
11674                       break;
11675                     default:
11676                       break;
11677                   }
11678
11679                   if (profile_str) {
11680                     gst_caps_set_simple (entry->caps,
11681                         "profile", G_TYPE_STRING, profile_str, NULL);
11682                   }
11683
11684                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11685                    * but webm spec define various ones. Add level to caps
11686                    * if we really need it then */
11687
11688                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11689                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11690                     gst_caps_set_simple (entry->caps,
11691                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11692                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11693                   }
11694
11695                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
11696                   switch (chroma_format) {
11697                     case 0:
11698                     case 1:
11699                       chroma_format_str = "4:2:0";
11700                       break;
11701                     case 2:
11702                       chroma_format_str = "4:2:2";
11703                       break;
11704                     case 3:
11705                       chroma_format_str = "4:4:4";
11706                       break;
11707                     default:
11708                       break;
11709                   }
11710
11711                   if (chroma_format_str) {
11712                     gst_caps_set_simple (entry->caps,
11713                         "chroma-format", G_TYPE_STRING, chroma_format_str,
11714                         NULL);
11715                   }
11716
11717                   if ((vpcc_data[14] & 0x1) != 0)
11718                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
11719                   else
11720                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
11721                   cinfo.primaries =
11722                       gst_video_color_primaries_from_iso (vpcc_data[15]);
11723                   cinfo.transfer =
11724                       gst_video_color_transfer_from_iso (vpcc_data[16]);
11725                   cinfo.matrix =
11726                       gst_video_color_matrix_from_iso (vpcc_data[17]);
11727
11728                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
11729                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
11730                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
11731                     /* set this only if all values are known, otherwise this
11732                      * might overwrite valid ones parsed from other color box */
11733                     CUR_STREAM (stream)->colorimetry = cinfo;
11734                   }
11735                   break;
11736                 }
11737                 default:
11738                   break;
11739               }
11740
11741               len -= size + 8;
11742               vpcc_data += size + 8;
11743             }
11744
11745             break;
11746           }
11747           default:
11748             break;
11749         }
11750       }
11751
11752       GST_INFO_OBJECT (qtdemux,
11753           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11754           GST_FOURCC_ARGS (fourcc), entry->caps);
11755
11756     } else if (stream->subtype == FOURCC_soun) {
11757       GNode *wave;
11758       int version, samplesize;
11759       guint16 compression_id;
11760       gboolean amrwb = FALSE;
11761
11762       offset = 16;
11763       /* sample description entry (16) + sound sample description v0 (20) */
11764       if (len < 36)
11765         goto corrupt_file;
11766
11767       version = QT_UINT32 (stsd_entry_data + offset);
11768       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11769       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11770       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11771       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11772
11773       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11774       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11775           QT_UINT32 (stsd_entry_data + offset + 4));
11776       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11777       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11778       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11779       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11780           QT_UINT16 (stsd_entry_data + offset + 14));
11781       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11782
11783       if (compression_id == 0xfffe)
11784         entry->sampled = TRUE;
11785
11786       /* first assume uncompressed audio */
11787       entry->bytes_per_sample = samplesize / 8;
11788       entry->samples_per_frame = entry->n_channels;
11789       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11790       entry->samples_per_packet = entry->samples_per_frame;
11791       entry->bytes_per_packet = entry->bytes_per_sample;
11792
11793       offset = 36;
11794
11795       if (version == 0x00010000) {
11796         /* sample description entry (16) + sound sample description v1 (20+16) */
11797         if (len < 52)
11798           goto corrupt_file;
11799
11800         /* take information from here over the normal sample description */
11801         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11802         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11803         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11804         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11805
11806         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
11807         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11808             entry->samples_per_packet);
11809         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11810             entry->bytes_per_packet);
11811         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11812             entry->bytes_per_frame);
11813         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11814             entry->bytes_per_sample);
11815
11816         if (!entry->sampled && entry->bytes_per_packet) {
11817           entry->samples_per_frame = (entry->bytes_per_frame /
11818               entry->bytes_per_packet) * entry->samples_per_packet;
11819           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11820               entry->samples_per_frame);
11821         }
11822       } else if (version == 0x00020000) {
11823         /* sample description entry (16) + sound sample description v2 (56) */
11824         if (len < 72)
11825           goto corrupt_file;
11826
11827         /* take information from here over the normal sample description */
11828         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
11829         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11830         entry->samples_per_frame = entry->n_channels;
11831         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
11832         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
11833         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
11834         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
11835
11836         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11837         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11838         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11839         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11840             entry->bytes_per_sample * 8);
11841         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11842             QT_UINT32 (stsd_entry_data + offset + 24));
11843         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11844             entry->bytes_per_packet);
11845         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11846             entry->samples_per_packet);
11847       } else if (version != 0x00000) {
11848         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11849             version);
11850       }
11851
11852       switch (fourcc) {
11853           /* Yes, these have to be hard-coded */
11854         case FOURCC_MAC6:
11855         {
11856           entry->samples_per_packet = 6;
11857           entry->bytes_per_packet = 1;
11858           entry->bytes_per_frame = 1 * entry->n_channels;
11859           entry->bytes_per_sample = 1;
11860           entry->samples_per_frame = 6 * entry->n_channels;
11861           break;
11862         }
11863         case FOURCC_MAC3:
11864         {
11865           entry->samples_per_packet = 3;
11866           entry->bytes_per_packet = 1;
11867           entry->bytes_per_frame = 1 * entry->n_channels;
11868           entry->bytes_per_sample = 1;
11869           entry->samples_per_frame = 3 * entry->n_channels;
11870           break;
11871         }
11872         case FOURCC_ima4:
11873         {
11874           entry->samples_per_packet = 64;
11875           entry->bytes_per_packet = 34;
11876           entry->bytes_per_frame = 34 * entry->n_channels;
11877           entry->bytes_per_sample = 2;
11878           entry->samples_per_frame = 64 * entry->n_channels;
11879           break;
11880         }
11881         case FOURCC_ulaw:
11882         case FOURCC_alaw:
11883         {
11884           entry->samples_per_packet = 1;
11885           entry->bytes_per_packet = 1;
11886           entry->bytes_per_frame = 1 * entry->n_channels;
11887           entry->bytes_per_sample = 1;
11888           entry->samples_per_frame = 1 * entry->n_channels;
11889           break;
11890         }
11891         case FOURCC_agsm:
11892         {
11893           entry->samples_per_packet = 160;
11894           entry->bytes_per_packet = 33;
11895           entry->bytes_per_frame = 33 * entry->n_channels;
11896           entry->bytes_per_sample = 2;
11897           entry->samples_per_frame = 160 * entry->n_channels;
11898           break;
11899         }
11900           /* fix up any invalid header information from above */
11901         case FOURCC_twos:
11902         case FOURCC_sowt:
11903         case FOURCC_raw_:
11904         case FOURCC_lpcm:
11905           /* Sometimes these are set to 0 in the sound sample descriptions so
11906            * let's try to infer useful values from the other information we
11907            * have available */
11908           if (entry->bytes_per_sample == 0)
11909             entry->bytes_per_sample =
11910                 entry->bytes_per_frame / entry->n_channels;
11911           if (entry->bytes_per_sample == 0)
11912             entry->bytes_per_sample = samplesize / 8;
11913
11914           if (entry->bytes_per_frame == 0)
11915             entry->bytes_per_frame =
11916                 entry->bytes_per_sample * entry->n_channels;
11917
11918           if (entry->bytes_per_packet == 0)
11919             entry->bytes_per_packet = entry->bytes_per_sample;
11920
11921           if (entry->samples_per_frame == 0)
11922             entry->samples_per_frame = entry->n_channels;
11923
11924           if (entry->samples_per_packet == 0)
11925             entry->samples_per_packet = entry->samples_per_frame;
11926
11927           break;
11928         case FOURCC_in24:
11929         case FOURCC_in32:
11930         case FOURCC_fl32:
11931         case FOURCC_fl64:
11932         case FOURCC_s16l:{
11933           switch (fourcc) {
11934             case FOURCC_in24:
11935               entry->bytes_per_sample = 3;
11936               break;
11937             case FOURCC_in32:
11938             case FOURCC_fl32:
11939               entry->bytes_per_sample = 4;
11940               break;
11941             case FOURCC_fl64:
11942               entry->bytes_per_sample = 8;
11943               break;
11944             case FOURCC_s16l:
11945               entry->bytes_per_sample = 2;
11946               break;
11947             default:
11948               g_assert_not_reached ();
11949               break;
11950           }
11951           entry->samples_per_frame = entry->n_channels;
11952           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11953           entry->samples_per_packet = entry->samples_per_frame;
11954           entry->bytes_per_packet = entry->bytes_per_sample;
11955           break;
11956         }
11957         default:
11958           break;
11959       }
11960
11961       if (entry->caps)
11962         gst_caps_unref (entry->caps);
11963
11964       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11965           stsd_entry_data + 32, len - 16, &codec);
11966
11967       switch (fourcc) {
11968         case FOURCC_in24:
11969         case FOURCC_in32:
11970         case FOURCC_fl32:
11971         case FOURCC_fl64:
11972         {
11973           GNode *enda;
11974           GNode *fmt;
11975
11976           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
11977
11978           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
11979           if (!enda) {
11980             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
11981             if (wave)
11982               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11983           }
11984           if (enda) {
11985             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11986             const gchar *format_str;
11987
11988             switch (fourcc) {
11989               case FOURCC_in24:
11990                 format_str = (enda_value) ? "S24LE" : "S24BE";
11991                 break;
11992               case FOURCC_in32:
11993                 format_str = (enda_value) ? "S32LE" : "S32BE";
11994                 break;
11995               case FOURCC_fl32:
11996                 format_str = (enda_value) ? "F32LE" : "F32BE";
11997                 break;
11998               case FOURCC_fl64:
11999                 format_str = (enda_value) ? "F64LE" : "F64BE";
12000                 break;
12001               default:
12002                 g_assert_not_reached ();
12003                 break;
12004             }
12005             gst_caps_set_simple (entry->caps,
12006                 "format", G_TYPE_STRING, format_str, NULL);
12007           }
12008           break;
12009         }
12010         case FOURCC_owma:
12011         {
12012           const guint8 *owma_data;
12013           const gchar *codec_name = NULL;
12014           guint owma_len;
12015           GstBuffer *buf;
12016           gint version = 1;
12017           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12018           /* FIXME this should also be gst_riff_strf_auds,
12019            * but the latter one is actually missing bits-per-sample :( */
12020           typedef struct
12021           {
12022             gint16 wFormatTag;
12023             gint16 nChannels;
12024             gint32 nSamplesPerSec;
12025             gint32 nAvgBytesPerSec;
12026             gint16 nBlockAlign;
12027             gint16 wBitsPerSample;
12028             gint16 cbSize;
12029           } WAVEFORMATEX;
12030           WAVEFORMATEX *wfex;
12031
12032           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12033           owma_data = stsd_entry_data;
12034           owma_len = QT_UINT32 (owma_data);
12035           if (owma_len <= 54) {
12036             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12037             break;
12038           }
12039           wfex = (WAVEFORMATEX *) (owma_data + 36);
12040           buf = gst_buffer_new_and_alloc (owma_len - 54);
12041           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12042           if (wfex->wFormatTag == 0x0161) {
12043             codec_name = "Windows Media Audio";
12044             version = 2;
12045           } else if (wfex->wFormatTag == 0x0162) {
12046             codec_name = "Windows Media Audio 9 Pro";
12047             version = 3;
12048           } else if (wfex->wFormatTag == 0x0163) {
12049             codec_name = "Windows Media Audio 9 Lossless";
12050             /* is that correct? gstffmpegcodecmap.c is missing it, but
12051              * fluendo codec seems to support it */
12052             version = 4;
12053           }
12054
12055           gst_caps_set_simple (entry->caps,
12056               "codec_data", GST_TYPE_BUFFER, buf,
12057               "wmaversion", G_TYPE_INT, version,
12058               "block_align", G_TYPE_INT,
12059               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12060               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12061               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12062               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12063           gst_buffer_unref (buf);
12064
12065           if (codec_name) {
12066             g_free (codec);
12067             codec = g_strdup (codec_name);
12068           }
12069           break;
12070         }
12071         case FOURCC_wma_:
12072         {
12073           gint len = QT_UINT32 (stsd_entry_data) - offset;
12074           const guint8 *wfex_data = stsd_entry_data + offset;
12075           const gchar *codec_name = NULL;
12076           gint version = 1;
12077           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12078           /* FIXME this should also be gst_riff_strf_auds,
12079            * but the latter one is actually missing bits-per-sample :( */
12080           typedef struct
12081           {
12082             gint16 wFormatTag;
12083             gint16 nChannels;
12084             gint32 nSamplesPerSec;
12085             gint32 nAvgBytesPerSec;
12086             gint16 nBlockAlign;
12087             gint16 wBitsPerSample;
12088             gint16 cbSize;
12089           } WAVEFORMATEX;
12090           WAVEFORMATEX wfex;
12091
12092           /* FIXME: unify with similar wavformatex parsing code above */
12093           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12094
12095           /* find wfex */
12096           while (len >= 8) {
12097             gint size;
12098
12099             if (QT_UINT32 (wfex_data) <= len)
12100               size = QT_UINT32 (wfex_data) - 8;
12101             else
12102               size = len - 8;
12103
12104             if (size < 1)
12105               /* No real data, so break out */
12106               break;
12107
12108             switch (QT_FOURCC (wfex_data + 4)) {
12109               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12110               {
12111                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12112
12113                 if (size < 8 + 18)
12114                   break;
12115
12116                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12117                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12118                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12119                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12120                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12121                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12122                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12123
12124                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12125                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12126                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12127                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12128                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12129                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12130
12131                 if (wfex.wFormatTag == 0x0161) {
12132                   codec_name = "Windows Media Audio";
12133                   version = 2;
12134                 } else if (wfex.wFormatTag == 0x0162) {
12135                   codec_name = "Windows Media Audio 9 Pro";
12136                   version = 3;
12137                 } else if (wfex.wFormatTag == 0x0163) {
12138                   codec_name = "Windows Media Audio 9 Lossless";
12139                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12140                    * fluendo codec seems to support it */
12141                   version = 4;
12142                 }
12143
12144                 gst_caps_set_simple (entry->caps,
12145                     "wmaversion", G_TYPE_INT, version,
12146                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12147                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12148                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12149                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12150
12151                 if (size > wfex.cbSize) {
12152                   GstBuffer *buf;
12153
12154                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12155                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12156                       size - wfex.cbSize);
12157                   gst_caps_set_simple (entry->caps,
12158                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12159                   gst_buffer_unref (buf);
12160                 } else {
12161                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12162                 }
12163
12164                 if (codec_name) {
12165                   g_free (codec);
12166                   codec = g_strdup (codec_name);
12167                 }
12168                 break;
12169               }
12170               default:
12171                 break;
12172             }
12173             len -= size + 8;
12174             wfex_data += size + 8;
12175           }
12176           break;
12177         }
12178         case FOURCC_opus:
12179         {
12180           const guint8 *opus_data;
12181           guint8 *channel_mapping = NULL;
12182           guint32 rate;
12183           guint8 channels;
12184           guint8 channel_mapping_family;
12185           guint8 stream_count;
12186           guint8 coupled_count;
12187           guint8 i;
12188
12189           opus_data = stsd_entry_data;
12190
12191           channels = GST_READ_UINT8 (opus_data + 45);
12192           rate = GST_READ_UINT32_LE (opus_data + 48);
12193           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12194           stream_count = GST_READ_UINT8 (opus_data + 55);
12195           coupled_count = GST_READ_UINT8 (opus_data + 56);
12196
12197           if (channels > 0) {
12198             channel_mapping = g_malloc (channels * sizeof (guint8));
12199             for (i = 0; i < channels; i++)
12200               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12201           }
12202
12203           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12204               channel_mapping_family, stream_count, coupled_count,
12205               channel_mapping);
12206           break;
12207         }
12208         default:
12209           break;
12210       }
12211
12212       if (codec) {
12213         GstStructure *s;
12214         gint bitrate = 0;
12215
12216         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12217             GST_TAG_AUDIO_CODEC, codec, NULL);
12218         g_free (codec);
12219         codec = NULL;
12220
12221         /* some bitrate info may have ended up in caps */
12222         s = gst_caps_get_structure (entry->caps, 0);
12223         gst_structure_get_int (s, "bitrate", &bitrate);
12224         if (bitrate > 0)
12225           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12226               GST_TAG_BITRATE, bitrate, NULL);
12227       }
12228
12229       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12230       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12231         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca)
12232           mp4a = NULL;
12233         else if (!stream->protected)
12234           mp4a = NULL;
12235       }
12236
12237       wave = NULL;
12238       esds = NULL;
12239       if (mp4a) {
12240         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12241         if (wave)
12242           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12243         if (!esds)
12244           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12245       }
12246
12247
12248       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12249          16 bits is a byte-swapped wave-style codec identifier,
12250          and we can find a WAVE header internally to a 'wave' atom here.
12251          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12252          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12253          is big-endian).
12254        */
12255       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12256         if (len < offset + 20) {
12257           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12258         } else {
12259           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12260           const guint8 *data = stsd_entry_data + offset + 16;
12261           GNode *wavenode;
12262           GNode *waveheadernode;
12263
12264           wavenode = g_node_new ((guint8 *) data);
12265           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12266             const guint8 *waveheader;
12267             guint32 headerlen;
12268
12269             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12270             if (waveheadernode) {
12271               waveheader = (const guint8 *) waveheadernode->data;
12272               headerlen = QT_UINT32 (waveheader);
12273
12274               if (headerlen > 8) {
12275                 gst_riff_strf_auds *header = NULL;
12276                 GstBuffer *headerbuf;
12277                 GstBuffer *extra;
12278
12279                 waveheader += 8;
12280                 headerlen -= 8;
12281
12282                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12283                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12284
12285                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12286                         headerbuf, &header, &extra)) {
12287                   gst_caps_unref (entry->caps);
12288                   /* FIXME: Need to do something with the channel reorder map */
12289                   entry->caps =
12290                       gst_riff_create_audio_caps (header->format, NULL, header,
12291                       extra, NULL, NULL, NULL);
12292
12293                   if (extra)
12294                     gst_buffer_unref (extra);
12295                   g_free (header);
12296                 }
12297               }
12298             } else
12299               GST_DEBUG ("Didn't find waveheadernode for this codec");
12300           }
12301           g_node_destroy (wavenode);
12302         }
12303       } else if (esds) {
12304         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12305             stream->stream_tags);
12306       } else {
12307         switch (fourcc) {
12308 #if 0
12309             /* FIXME: what is in the chunk? */
12310           case FOURCC_QDMC:
12311           {
12312             gint len = QT_UINT32 (stsd_data);
12313
12314             /* seems to be always = 116 = 0x74 */
12315             break;
12316           }
12317 #endif
12318           case FOURCC_QDM2:
12319           {
12320             gint len = QT_UINT32 (stsd_entry_data);
12321
12322             if (len > 0x3C) {
12323               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12324
12325               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12326               gst_caps_set_simple (entry->caps,
12327                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12328               gst_buffer_unref (buf);
12329             }
12330             gst_caps_set_simple (entry->caps,
12331                 "samplesize", G_TYPE_INT, samplesize, NULL);
12332             break;
12333           }
12334           case FOURCC_alac:
12335           {
12336             GNode *alac, *wave = NULL;
12337
12338             /* apparently, m4a has this atom appended directly in the stsd entry,
12339              * while mov has it in a wave atom */
12340             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12341             if (alac) {
12342               /* alac now refers to stsd entry atom */
12343               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12344               if (wave)
12345                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12346               else
12347                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12348             }
12349             if (alac) {
12350               const guint8 *alac_data = alac->data;
12351               gint len = QT_UINT32 (alac->data);
12352               GstBuffer *buf;
12353
12354               if (len < 36) {
12355                 GST_DEBUG_OBJECT (qtdemux,
12356                     "discarding alac atom with unexpected len %d", len);
12357               } else {
12358                 /* codec-data contains alac atom size and prefix,
12359                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12360                 buf = gst_buffer_new_and_alloc (len);
12361                 gst_buffer_fill (buf, 0, alac->data, len);
12362                 gst_caps_set_simple (entry->caps,
12363                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12364                 gst_buffer_unref (buf);
12365
12366                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12367                 entry->n_channels = QT_UINT8 (alac_data + 21);
12368                 entry->rate = QT_UINT32 (alac_data + 32);
12369               }
12370             }
12371             gst_caps_set_simple (entry->caps,
12372                 "samplesize", G_TYPE_INT, samplesize, NULL);
12373             break;
12374           }
12375           case FOURCC_fLaC:
12376           {
12377             /* The codingname of the sample entry is 'fLaC' */
12378             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12379
12380             if (flac) {
12381               /* The 'dfLa' box is added to the sample entry to convey
12382                  initializing information for the decoder. */
12383               const GNode *dfla =
12384                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12385
12386               if (dfla) {
12387                 const guint32 len = QT_UINT32 (dfla->data);
12388
12389                 /* Must contain at least dfLa box header (12),
12390                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12391                 if (len < 50) {
12392                   GST_DEBUG_OBJECT (qtdemux,
12393                       "discarding dfla atom with unexpected len %d", len);
12394                 } else {
12395                   /* skip dfLa header to get the METADATA_BLOCKs */
12396                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12397                   const guint32 metadata_blocks_len = len - 12;
12398
12399                   gchar *stream_marker = g_strdup ("fLaC");
12400                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12401                       strlen (stream_marker));
12402
12403                   guint32 index = 0;
12404                   guint32 remainder = 0;
12405                   guint32 block_size = 0;
12406                   gboolean is_last = FALSE;
12407
12408                   GValue array = G_VALUE_INIT;
12409                   GValue value = G_VALUE_INIT;
12410
12411                   g_value_init (&array, GST_TYPE_ARRAY);
12412                   g_value_init (&value, GST_TYPE_BUFFER);
12413
12414                   gst_value_set_buffer (&value, block);
12415                   gst_value_array_append_value (&array, &value);
12416                   g_value_reset (&value);
12417
12418                   gst_buffer_unref (block);
12419
12420                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12421                    * of data, and we haven't already finished parsing */
12422                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12423                     remainder = metadata_blocks_len - index;
12424
12425                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12426                     block_size = 4 +
12427                         (metadata_blocks[index + 1] << 16) +
12428                         (metadata_blocks[index + 2] << 8) +
12429                         metadata_blocks[index + 3];
12430
12431                     /* be careful not to read off end of box */
12432                     if (block_size > remainder) {
12433                       break;
12434                     }
12435
12436                     is_last = metadata_blocks[index] >> 7;
12437
12438                     block = gst_buffer_new_and_alloc (block_size);
12439
12440                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12441                         block_size);
12442
12443                     gst_value_set_buffer (&value, block);
12444                     gst_value_array_append_value (&array, &value);
12445                     g_value_reset (&value);
12446
12447                     gst_buffer_unref (block);
12448
12449                     index += block_size;
12450                   }
12451
12452                   /* only append the metadata if we successfully read all of it */
12453                   if (is_last) {
12454                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12455                             (stream)->caps, 0), "streamheader", &array);
12456                   } else {
12457                     GST_WARNING_OBJECT (qtdemux,
12458                         "discarding all METADATA_BLOCKs due to invalid "
12459                         "block_size %d at idx %d, rem %d", block_size, index,
12460                         remainder);
12461                   }
12462
12463                   g_value_unset (&value);
12464                   g_value_unset (&array);
12465
12466                   /* The sample rate obtained from the stsd may not be accurate
12467                    * since it cannot represent rates greater than 65535Hz, so
12468                    * override that value with the sample rate from the
12469                    * METADATA_BLOCK_STREAMINFO block */
12470                   CUR_STREAM (stream)->rate =
12471                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12472                 }
12473               }
12474             }
12475             break;
12476           }
12477           case FOURCC_sawb:
12478             /* Fallthrough! */
12479             amrwb = TRUE;
12480           case FOURCC_samr:
12481           {
12482             gint len = QT_UINT32 (stsd_entry_data);
12483
12484             if (len > 0x24) {
12485               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12486               guint bitrate;
12487
12488               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12489
12490               /* If we have enough data, let's try to get the 'damr' atom. See
12491                * the 3GPP container spec (26.244) for more details. */
12492               if ((len - 0x34) > 8 &&
12493                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12494                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12495                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12496               }
12497
12498               gst_caps_set_simple (entry->caps,
12499                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12500               gst_buffer_unref (buf);
12501             }
12502             break;
12503           }
12504           case FOURCC_mp4a:
12505           {
12506             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12507             gint len = QT_UINT32 (stsd_entry_data);
12508
12509             if (len >= 34) {
12510               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12511
12512               if (sound_version == 1) {
12513                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12514                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12515                 guint8 codec_data[2];
12516                 GstBuffer *buf;
12517                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12518
12519                 gint sample_rate_index =
12520                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12521
12522                 /* build AAC codec data */
12523                 codec_data[0] = profile << 3;
12524                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12525                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12526                 codec_data[1] |= (channels & 0xF) << 3;
12527
12528                 buf = gst_buffer_new_and_alloc (2);
12529                 gst_buffer_fill (buf, 0, codec_data, 2);
12530                 gst_caps_set_simple (entry->caps,
12531                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12532                 gst_buffer_unref (buf);
12533               }
12534             }
12535             break;
12536           }
12537           case FOURCC_lpcm:
12538           case FOURCC_in24:
12539           case FOURCC_in32:
12540           case FOURCC_fl32:
12541           case FOURCC_fl64:
12542           case FOURCC_s16l:
12543             /* Fully handled elsewhere */
12544             break;
12545           default:
12546             GST_INFO_OBJECT (qtdemux,
12547                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12548             break;
12549         }
12550       }
12551       GST_INFO_OBJECT (qtdemux,
12552           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12553           GST_FOURCC_ARGS (fourcc), entry->caps);
12554
12555     } else if (stream->subtype == FOURCC_strm) {
12556       if (fourcc == FOURCC_rtsp) {
12557         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12558       } else {
12559         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12560             GST_FOURCC_ARGS (fourcc));
12561         goto unknown_stream;
12562       }
12563       entry->sampled = TRUE;
12564     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12565         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12566         || stream->subtype == FOURCC_clcp) {
12567
12568       entry->sampled = TRUE;
12569       entry->sparse = TRUE;
12570
12571       entry->caps =
12572           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12573           &codec);
12574       if (codec) {
12575         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12576             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12577         g_free (codec);
12578         codec = NULL;
12579       }
12580
12581       /* hunt for sort-of codec data */
12582       switch (fourcc) {
12583         case FOURCC_mp4s:
12584         {
12585           GNode *mp4s = NULL;
12586           GNode *esds = NULL;
12587
12588           /* look for palette in a stsd->mp4s->esds sub-atom */
12589           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12590           if (mp4s)
12591             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12592           if (esds == NULL) {
12593             /* Invalid STSD */
12594             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12595             break;
12596           }
12597
12598           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12599               stream->stream_tags);
12600           break;
12601         }
12602         default:
12603           GST_INFO_OBJECT (qtdemux,
12604               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12605           break;
12606       }
12607       GST_INFO_OBJECT (qtdemux,
12608           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12609           GST_FOURCC_ARGS (fourcc), entry->caps);
12610     } else {
12611       /* everything in 1 sample */
12612       entry->sampled = TRUE;
12613
12614       entry->caps =
12615           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12616           &codec);
12617
12618       if (entry->caps == NULL)
12619         goto unknown_stream;
12620
12621       if (codec) {
12622         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12623             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12624         g_free (codec);
12625         codec = NULL;
12626       }
12627     }
12628
12629     /* promote to sampled format */
12630     if (entry->fourcc == FOURCC_samr) {
12631       /* force mono 8000 Hz for AMR */
12632       entry->sampled = TRUE;
12633       entry->n_channels = 1;
12634       entry->rate = 8000;
12635     } else if (entry->fourcc == FOURCC_sawb) {
12636       /* force mono 16000 Hz for AMR-WB */
12637       entry->sampled = TRUE;
12638       entry->n_channels = 1;
12639       entry->rate = 16000;
12640     } else if (entry->fourcc == FOURCC_mp4a) {
12641       entry->sampled = TRUE;
12642     }
12643
12644
12645     stsd_entry_data += len;
12646     remaining_stsd_len -= len;
12647
12648   }
12649
12650   /* collect sample information */
12651   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12652     goto samples_failed;
12653
12654   if (qtdemux->fragmented) {
12655     guint64 offset;
12656
12657     /* need all moov samples as basis; probably not many if any at all */
12658     /* prevent moof parsing taking of at this time */
12659     offset = qtdemux->moof_offset;
12660     qtdemux->moof_offset = 0;
12661     if (stream->n_samples &&
12662         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12663       qtdemux->moof_offset = offset;
12664       goto samples_failed;
12665     }
12666     qtdemux->moof_offset = 0;
12667     /* movie duration more reliable in this case (e.g. mehd) */
12668     if (qtdemux->segment.duration &&
12669         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12670       stream->duration =
12671           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12672   }
12673
12674   /* configure segments */
12675   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12676     goto segments_failed;
12677
12678   /* add some language tag, if useful */
12679   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12680       strcmp (stream->lang_id, "und")) {
12681     const gchar *lang_code;
12682
12683     /* convert ISO 639-2 code to ISO 639-1 */
12684     lang_code = gst_tag_get_language_code (stream->lang_id);
12685     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12686         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12687   }
12688
12689   /* Check for UDTA tags */
12690   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12691     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12692   }
12693
12694   /* Insert and sort new stream in track-id order.
12695    * This will help in comparing old/new streams during stream update check */
12696   g_ptr_array_add (qtdemux->active_streams, stream);
12697   g_ptr_array_sort (qtdemux->active_streams,
12698       (GCompareFunc) qtdemux_track_id_compare_func);
12699   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12700       QTDEMUX_N_STREAMS (qtdemux));
12701
12702   return TRUE;
12703
12704 /* ERRORS */
12705 corrupt_file:
12706   {
12707     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12708         (_("This file is corrupt and cannot be played.")), (NULL));
12709     if (stream)
12710       gst_qtdemux_stream_unref (stream);
12711     return FALSE;
12712   }
12713 error_encrypted:
12714   {
12715     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12716     gst_qtdemux_stream_unref (stream);
12717     return FALSE;
12718   }
12719 samples_failed:
12720 segments_failed:
12721   {
12722     /* we posted an error already */
12723     /* free stbl sub-atoms */
12724     gst_qtdemux_stbl_free (stream);
12725     gst_qtdemux_stream_unref (stream);
12726     return FALSE;
12727   }
12728 existing_stream:
12729   {
12730     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12731         track_id);
12732     return TRUE;
12733   }
12734 unknown_stream:
12735   {
12736     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12737         GST_FOURCC_ARGS (stream->subtype));
12738     gst_qtdemux_stream_unref (stream);
12739     return TRUE;
12740   }
12741 }
12742
12743 /* If we can estimate the overall bitrate, and don't have information about the
12744  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12745  * the overall bitrate minus the sum of the bitrates of all other streams. This
12746  * should be useful for the common case where we have one audio and one video
12747  * stream and can estimate the bitrate of one, but not the other. */
12748 static void
12749 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12750 {
12751   QtDemuxStream *stream = NULL;
12752   gint64 size, sys_bitrate, sum_bitrate = 0;
12753   GstClockTime duration;
12754   guint bitrate;
12755   gint i;
12756
12757   if (qtdemux->fragmented)
12758     return;
12759
12760   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12761
12762   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12763       || size <= 0) {
12764     GST_DEBUG_OBJECT (qtdemux,
12765         "Size in bytes of the stream not known - bailing");
12766     return;
12767   }
12768
12769   /* Subtract the header size */
12770   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12771       size, qtdemux->header_size);
12772
12773   if (size < qtdemux->header_size)
12774     return;
12775
12776   size = size - qtdemux->header_size;
12777
12778   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12779     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12780     return;
12781   }
12782
12783   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12784     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12785     switch (str->subtype) {
12786       case FOURCC_soun:
12787       case FOURCC_vide:
12788         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12789             CUR_STREAM (str)->caps);
12790         /* retrieve bitrate, prefer avg then max */
12791         bitrate = 0;
12792         if (str->stream_tags) {
12793           if (gst_tag_list_get_uint (str->stream_tags,
12794                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12795             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12796           if (gst_tag_list_get_uint (str->stream_tags,
12797                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12798             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12799           if (gst_tag_list_get_uint (str->stream_tags,
12800                   GST_TAG_BITRATE, &bitrate))
12801             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12802         }
12803         if (bitrate)
12804           sum_bitrate += bitrate;
12805         else {
12806           if (stream) {
12807             GST_DEBUG_OBJECT (qtdemux,
12808                 ">1 stream with unknown bitrate - bailing");
12809             return;
12810           } else
12811             stream = str;
12812         }
12813
12814       default:
12815         /* For other subtypes, we assume no significant impact on bitrate */
12816         break;
12817     }
12818   }
12819
12820   if (!stream) {
12821     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12822     return;
12823   }
12824
12825   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12826
12827   if (sys_bitrate < sum_bitrate) {
12828     /* This can happen, since sum_bitrate might be derived from maximum
12829      * bitrates and not average bitrates */
12830     GST_DEBUG_OBJECT (qtdemux,
12831         "System bitrate less than sum bitrate - bailing");
12832     return;
12833   }
12834
12835   bitrate = sys_bitrate - sum_bitrate;
12836   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12837       ", Stream bitrate = %u", sys_bitrate, bitrate);
12838
12839   if (!stream->stream_tags)
12840     stream->stream_tags = gst_tag_list_new_empty ();
12841   else
12842     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12843
12844   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12845       GST_TAG_BITRATE, bitrate, NULL);
12846 }
12847
12848 static GstFlowReturn
12849 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12850 {
12851   GstFlowReturn ret = GST_FLOW_OK;
12852   gint i;
12853
12854   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12855
12856   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12857     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12858     guint32 sample_num = 0;
12859
12860     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12861         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12862
12863     if (qtdemux->fragmented) {
12864       /* need all moov samples first */
12865       GST_OBJECT_LOCK (qtdemux);
12866       while (stream->n_samples == 0)
12867         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12868           break;
12869       GST_OBJECT_UNLOCK (qtdemux);
12870     } else {
12871       /* discard any stray moof */
12872       qtdemux->moof_offset = 0;
12873     }
12874
12875     /* prepare braking */
12876     if (ret != GST_FLOW_ERROR)
12877       ret = GST_FLOW_OK;
12878
12879     /* in pull mode, we should have parsed some sample info by now;
12880      * and quite some code will not handle no samples.
12881      * in push mode, we'll just have to deal with it */
12882     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12883       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12884       g_ptr_array_remove_index (qtdemux->active_streams, i);
12885       i--;
12886       continue;
12887     } else if (stream->track_id == qtdemux->chapters_track_id &&
12888         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12889       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12890          so that it doesn't look like a subtitle track */
12891       g_ptr_array_remove_index (qtdemux->active_streams, i);
12892       i--;
12893       continue;
12894     }
12895
12896     /* parse the initial sample for use in setting the frame rate cap */
12897     while (sample_num == 0 && sample_num < stream->n_samples) {
12898       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12899         break;
12900       ++sample_num;
12901     }
12902   }
12903
12904   return ret;
12905 }
12906
12907 static gboolean
12908 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
12909 {
12910   return g_strcmp0 (stream->stream_id, stream_id) == 0;
12911 }
12912
12913 static gboolean
12914 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12915 {
12916   gint i;
12917
12918   /* Different length, updated */
12919   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
12920     return TRUE;
12921
12922   /* streams in list are sorted in track-id order */
12923   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12924     /* Different stream-id, updated */
12925     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
12926             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
12927       return TRUE;
12928   }
12929
12930   return FALSE;
12931 }
12932
12933 static gboolean
12934 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12935     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12936 {
12937   /* Connect old stream's srcpad to new stream */
12938   newstream->pad = oldstream->pad;
12939   oldstream->pad = NULL;
12940
12941   /* unset new_stream to prevent stream-start event */
12942   newstream->new_stream = FALSE;
12943
12944   return gst_qtdemux_configure_stream (qtdemux, newstream);
12945 }
12946
12947 /* g_ptr_array_find_with_equal_func is available since 2.54,
12948  * replacement until we can depend unconditionally on the real one in GLib */
12949 #if !GLIB_CHECK_VERSION(2,54,0)
12950 #define g_ptr_array_find_with_equal_func qtdemux_ptr_array_find_with_equal_func
12951 static gboolean
12952 qtdemux_ptr_array_find_with_equal_func (GPtrArray * haystack,
12953     gconstpointer needle, GEqualFunc equal_func, guint * index_)
12954 {
12955   guint i;
12956
12957   g_return_val_if_fail (haystack != NULL, FALSE);
12958
12959   if (equal_func == NULL)
12960     equal_func = g_direct_equal;
12961
12962   for (i = 0; i < haystack->len; i++) {
12963     if (equal_func (g_ptr_array_index (haystack, i), needle)) {
12964       if (index_ != NULL)
12965         *index_ = i;
12966       return TRUE;
12967     }
12968   }
12969
12970   return FALSE;
12971 }
12972 #endif
12973
12974 static gboolean
12975 qtdemux_update_streams (GstQTDemux * qtdemux)
12976 {
12977   gint i;
12978   g_assert (qtdemux->streams_aware);
12979
12980   /* At below, figure out which stream in active_streams has identical stream-id
12981    * with that of in old_streams. If there is matching stream-id,
12982    * corresponding newstream will not be exposed again,
12983    * but demux will reuse srcpad of matched old stream
12984    *
12985    * active_streams : newly created streams from the latest moov
12986    * old_streams : existing streams (belong to previous moov)
12987    */
12988
12989   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12990     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12991     QtDemuxStream *oldstream = NULL;
12992     guint target;
12993
12994     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12995         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12996
12997     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
12998             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
12999       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13000
13001       /* null pad stream cannot be reused */
13002       if (oldstream->pad == NULL)
13003         oldstream = NULL;
13004     }
13005
13006     if (oldstream) {
13007       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13008
13009       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13010         return FALSE;
13011
13012       /* we don't need to preserve order of old streams */
13013       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13014     } else {
13015       GstTagList *list;
13016
13017       /* now we have all info and can expose */
13018       list = stream->stream_tags;
13019       stream->stream_tags = NULL;
13020       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13021         return FALSE;
13022     }
13023   }
13024
13025   return TRUE;
13026 }
13027
13028 /* Must be called with expose lock */
13029 static GstFlowReturn
13030 qtdemux_expose_streams (GstQTDemux * qtdemux)
13031 {
13032   gint i;
13033
13034   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13035
13036   if (!qtdemux_is_streams_update (qtdemux)) {
13037     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13038     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13039       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13040       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13041       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13042         return GST_FLOW_ERROR;
13043     }
13044
13045     g_ptr_array_set_size (qtdemux->old_streams, 0);
13046     qtdemux->need_segment = TRUE;
13047
13048     return GST_FLOW_OK;
13049   }
13050
13051   if (qtdemux->streams_aware) {
13052     if (!qtdemux_update_streams (qtdemux))
13053       return GST_FLOW_ERROR;
13054   } else {
13055     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13056       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13057       GstTagList *list;
13058
13059       /* now we have all info and can expose */
13060       list = stream->stream_tags;
13061       stream->stream_tags = NULL;
13062       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13063         return GST_FLOW_ERROR;
13064
13065     }
13066   }
13067
13068   gst_qtdemux_guess_bitrate (qtdemux);
13069
13070   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13071
13072   /* If we have still old_streams, it's no more used stream */
13073   for (i = 0; i < qtdemux->old_streams->len; i++) {
13074     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13075
13076     if (stream->pad) {
13077       GstEvent *event;
13078
13079       event = gst_event_new_eos ();
13080       if (qtdemux->segment_seqnum)
13081         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13082
13083       gst_pad_push_event (stream->pad, event);
13084     }
13085   }
13086
13087   g_ptr_array_set_size (qtdemux->old_streams, 0);
13088
13089   /* check if we should post a redirect in case there is a single trak
13090    * and it is a redirecting trak */
13091   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13092       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13093     GstMessage *m;
13094
13095     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13096         "an external content");
13097     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13098         gst_structure_new ("redirect",
13099             "new-location", G_TYPE_STRING,
13100             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13101     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13102     g_free (qtdemux->redirect_location);
13103     qtdemux->redirect_location =
13104         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13105   }
13106
13107   g_ptr_array_foreach (qtdemux->active_streams,
13108       (GFunc) qtdemux_do_allocation, qtdemux);
13109
13110   qtdemux->need_segment = TRUE;
13111
13112   qtdemux->exposed = TRUE;
13113   return GST_FLOW_OK;
13114 }
13115
13116 typedef struct
13117 {
13118   GstStructure *structure;      /* helper for sort function */
13119   gchar *location;
13120   guint min_req_bitrate;
13121   guint min_req_qt_version;
13122 } GstQtReference;
13123
13124 static gint
13125 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13126 {
13127   GstQtReference *ref_a = (GstQtReference *) a;
13128   GstQtReference *ref_b = (GstQtReference *) b;
13129
13130   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13131     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13132
13133   /* known bitrates go before unknown; higher bitrates go first */
13134   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13135 }
13136
13137 /* sort the redirects and post a message for the application.
13138  */
13139 static void
13140 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13141 {
13142   GstQtReference *best;
13143   GstStructure *s;
13144   GstMessage *msg;
13145   GValue list_val = { 0, };
13146   GList *l;
13147
13148   g_assert (references != NULL);
13149
13150   references = g_list_sort (references, qtdemux_redirects_sort_func);
13151
13152   best = (GstQtReference *) references->data;
13153
13154   g_value_init (&list_val, GST_TYPE_LIST);
13155
13156   for (l = references; l != NULL; l = l->next) {
13157     GstQtReference *ref = (GstQtReference *) l->data;
13158     GValue struct_val = { 0, };
13159
13160     ref->structure = gst_structure_new ("redirect",
13161         "new-location", G_TYPE_STRING, ref->location, NULL);
13162
13163     if (ref->min_req_bitrate > 0) {
13164       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13165           ref->min_req_bitrate, NULL);
13166     }
13167
13168     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13169     g_value_set_boxed (&struct_val, ref->structure);
13170     gst_value_list_append_value (&list_val, &struct_val);
13171     g_value_unset (&struct_val);
13172     /* don't free anything here yet, since we need best->structure below */
13173   }
13174
13175   g_assert (best != NULL);
13176   s = gst_structure_copy (best->structure);
13177
13178   if (g_list_length (references) > 1) {
13179     gst_structure_set_value (s, "locations", &list_val);
13180   }
13181
13182   g_value_unset (&list_val);
13183
13184   for (l = references; l != NULL; l = l->next) {
13185     GstQtReference *ref = (GstQtReference *) l->data;
13186
13187     gst_structure_free (ref->structure);
13188     g_free (ref->location);
13189     g_free (ref);
13190   }
13191   g_list_free (references);
13192
13193   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13194   g_free (qtdemux->redirect_location);
13195   qtdemux->redirect_location =
13196       g_strdup (gst_structure_get_string (s, "new-location"));
13197   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13198   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13199 }
13200
13201 /* look for redirect nodes, collect all redirect information and
13202  * process it.
13203  */
13204 static gboolean
13205 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13206 {
13207   GNode *rmra, *rmda, *rdrf;
13208
13209   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13210   if (rmra) {
13211     GList *redirects = NULL;
13212
13213     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13214     while (rmda) {
13215       GstQtReference ref = { NULL, NULL, 0, 0 };
13216       GNode *rmdr, *rmvc;
13217
13218       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13219         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13220         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13221             ref.min_req_bitrate);
13222       }
13223
13224       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13225         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13226         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13227
13228 #ifndef GST_DISABLE_GST_DEBUG
13229         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13230 #endif
13231         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13232
13233         GST_LOG_OBJECT (qtdemux,
13234             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13235             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13236             bitmask, check_type);
13237         if (package == FOURCC_qtim && check_type == 0) {
13238           ref.min_req_qt_version = version;
13239         }
13240       }
13241
13242       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13243       if (rdrf) {
13244         guint32 ref_type;
13245         guint8 *ref_data;
13246         guint ref_len;
13247
13248         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13249         if (ref_len > 20) {
13250           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13251           ref_data = (guint8 *) rdrf->data + 20;
13252           if (ref_type == FOURCC_alis) {
13253             guint record_len, record_version, fn_len;
13254
13255             if (ref_len > 70) {
13256               /* MacOSX alias record, google for alias-layout.txt */
13257               record_len = QT_UINT16 (ref_data + 4);
13258               record_version = QT_UINT16 (ref_data + 4 + 2);
13259               fn_len = QT_UINT8 (ref_data + 50);
13260               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13261                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13262               }
13263             } else {
13264               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13265                   ref_len);
13266             }
13267           } else if (ref_type == FOURCC_url_) {
13268             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13269           } else {
13270             GST_DEBUG_OBJECT (qtdemux,
13271                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13272                 GST_FOURCC_ARGS (ref_type));
13273           }
13274           if (ref.location != NULL) {
13275             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13276             redirects =
13277                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13278           } else {
13279             GST_WARNING_OBJECT (qtdemux,
13280                 "Failed to extract redirect location from rdrf atom");
13281           }
13282         } else {
13283           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13284         }
13285       }
13286
13287       /* look for others */
13288       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13289     }
13290
13291     if (redirects != NULL) {
13292       qtdemux_process_redirects (qtdemux, redirects);
13293     }
13294   }
13295   return TRUE;
13296 }
13297
13298 static GstTagList *
13299 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13300 {
13301   const gchar *fmt;
13302
13303   if (tags == NULL) {
13304     tags = gst_tag_list_new_empty ();
13305     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13306   }
13307
13308   if (qtdemux->major_brand == FOURCC_mjp2)
13309     fmt = "Motion JPEG 2000";
13310   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13311     fmt = "3GP";
13312   else if (qtdemux->major_brand == FOURCC_qt__)
13313     fmt = "Quicktime";
13314   else if (qtdemux->fragmented)
13315     fmt = "ISO fMP4";
13316   else
13317     fmt = "ISO MP4/M4A";
13318
13319   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13320       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13321
13322   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13323       fmt, NULL);
13324
13325   return tags;
13326 }
13327
13328 /* we have read the complete moov node now.
13329  * This function parses all of the relevant info, creates the traks and
13330  * prepares all data structures for playback
13331  */
13332 static gboolean
13333 qtdemux_parse_tree (GstQTDemux * qtdemux)
13334 {
13335   GNode *mvhd;
13336   GNode *trak;
13337   GNode *udta;
13338   GNode *mvex;
13339   GNode *pssh;
13340   guint64 creation_time;
13341   GstDateTime *datetime = NULL;
13342   gint version;
13343
13344   /* make sure we have a usable taglist */
13345   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13346
13347   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13348   if (mvhd == NULL) {
13349     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13350     return qtdemux_parse_redirects (qtdemux);
13351   }
13352
13353   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13354   if (version == 1) {
13355     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13356     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13357     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13358   } else if (version == 0) {
13359     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13360     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13361     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13362   } else {
13363     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13364     return FALSE;
13365   }
13366
13367   /* Moving qt creation time (secs since 1904) to unix time */
13368   if (creation_time != 0) {
13369     /* Try to use epoch first as it should be faster and more commonly found */
13370     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13371       gint64 now_s;
13372
13373       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13374       /* some data cleansing sanity */
13375       now_s = g_get_real_time () / G_USEC_PER_SEC;
13376       if (now_s + 24 * 3600 < creation_time) {
13377         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13378       } else {
13379         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13380       }
13381     } else {
13382       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13383       GDateTime *dt, *dt_local;
13384
13385       dt = g_date_time_add_seconds (base_dt, creation_time);
13386       dt_local = g_date_time_to_local (dt);
13387       datetime = gst_date_time_new_from_g_date_time (dt_local);
13388
13389       g_date_time_unref (base_dt);
13390       g_date_time_unref (dt);
13391     }
13392   }
13393   if (datetime) {
13394     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13395     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13396         datetime, NULL);
13397     gst_date_time_unref (datetime);
13398   }
13399
13400   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13401   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13402
13403   /* check for fragmented file and get some (default) data */
13404   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13405   if (mvex) {
13406     GNode *mehd;
13407     GstByteReader mehd_data;
13408
13409     /* let track parsing or anyone know weird stuff might happen ... */
13410     qtdemux->fragmented = TRUE;
13411
13412     /* compensate for total duration */
13413     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13414     if (mehd)
13415       qtdemux_parse_mehd (qtdemux, &mehd_data);
13416   }
13417
13418   /* Update the movie segment duration, unless it was directly given to us
13419    * by upstream. Otherwise let it as is, as we don't want to mangle the
13420    * duration provided by upstream that may come e.g. from a MPD file. */
13421   if (!qtdemux->upstream_format_is_time) {
13422     GstClockTime duration;
13423     /* set duration in the segment info */
13424     gst_qtdemux_get_duration (qtdemux, &duration);
13425     qtdemux->segment.duration = duration;
13426     /* also do not exceed duration; stop is set that way post seek anyway,
13427      * and segment activation falls back to duration,
13428      * whereas loop only checks stop, so let's align this here as well */
13429     qtdemux->segment.stop = duration;
13430   }
13431
13432   /* parse all traks */
13433   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13434   while (trak) {
13435     qtdemux_parse_trak (qtdemux, trak);
13436     /* iterate all siblings */
13437     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13438   }
13439
13440   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13441
13442   /* find tags */
13443   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13444   if (udta) {
13445     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13446   } else {
13447     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13448   }
13449
13450   /* maybe also some tags in meta box */
13451   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13452   if (udta) {
13453     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13454     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13455   } else {
13456     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13457   }
13458
13459   /* parse any protection system info */
13460   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13461   while (pssh) {
13462     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13463     qtdemux_parse_pssh (qtdemux, pssh);
13464     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13465   }
13466
13467   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13468
13469   return TRUE;
13470 }
13471
13472 /* taken from ffmpeg */
13473 static int
13474 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13475 {
13476   int count = 4;
13477   int len = 0;
13478
13479   while (count--) {
13480     int c;
13481
13482     if (ptr >= end)
13483       return -1;
13484
13485     c = *ptr++;
13486     len = (len << 7) | (c & 0x7f);
13487     if (!(c & 0x80))
13488       break;
13489   }
13490   *end_out = ptr;
13491   return len;
13492 }
13493
13494 static GList *
13495 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13496     gsize codec_data_size)
13497 {
13498   GList *list = NULL;
13499   guint8 *p = codec_data;
13500   gint i, offset, num_packets;
13501   guint *length, last;
13502
13503   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13504
13505   if (codec_data == NULL || codec_data_size == 0)
13506     goto error;
13507
13508   /* start of the stream and vorbis audio or theora video, need to
13509    * send the codec_priv data as first three packets */
13510   num_packets = p[0] + 1;
13511   GST_DEBUG_OBJECT (qtdemux,
13512       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13513       (guint) num_packets, codec_data_size);
13514
13515   /* Let's put some limits, Don't think there even is a xiph codec
13516    * with more than 3-4 headers */
13517   if (G_UNLIKELY (num_packets > 16)) {
13518     GST_WARNING_OBJECT (qtdemux,
13519         "Unlikely number of xiph headers, most likely not valid");
13520     goto error;
13521   }
13522
13523   length = g_alloca (num_packets * sizeof (guint));
13524   last = 0;
13525   offset = 1;
13526
13527   /* first packets, read length values */
13528   for (i = 0; i < num_packets - 1; i++) {
13529     length[i] = 0;
13530     while (offset < codec_data_size) {
13531       length[i] += p[offset];
13532       if (p[offset++] != 0xff)
13533         break;
13534     }
13535     last += length[i];
13536   }
13537   if (offset + last > codec_data_size)
13538     goto error;
13539
13540   /* last packet is the remaining size */
13541   length[i] = codec_data_size - offset - last;
13542
13543   for (i = 0; i < num_packets; i++) {
13544     GstBuffer *hdr;
13545
13546     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13547
13548     if (offset + length[i] > codec_data_size)
13549       goto error;
13550
13551     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13552     list = g_list_append (list, hdr);
13553
13554     offset += length[i];
13555   }
13556
13557   return list;
13558
13559   /* ERRORS */
13560 error:
13561   {
13562     if (list != NULL)
13563       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13564     return NULL;
13565   }
13566
13567 }
13568
13569 /* this can change the codec originally present in @list */
13570 static void
13571 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13572     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13573 {
13574   int len = QT_UINT32 (esds->data);
13575   guint8 *ptr = esds->data;
13576   guint8 *end = ptr + len;
13577   int tag;
13578   guint8 *data_ptr = NULL;
13579   int data_len = 0;
13580   guint8 object_type_id = 0;
13581   guint8 stream_type = 0;
13582   const char *codec_name = NULL;
13583   GstCaps *caps = NULL;
13584
13585   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13586   ptr += 8;
13587   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13588   ptr += 4;
13589   while (ptr + 1 < end) {
13590     tag = QT_UINT8 (ptr);
13591     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13592     ptr++;
13593     len = read_descr_size (ptr, end, &ptr);
13594     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13595
13596     /* Check the stated amount of data is available for reading */
13597     if (len < 0 || ptr + len > end)
13598       break;
13599
13600     switch (tag) {
13601       case ES_DESCRIPTOR_TAG:
13602         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13603         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13604         ptr += 3;
13605         break;
13606       case DECODER_CONFIG_DESC_TAG:{
13607         guint max_bitrate, avg_bitrate;
13608
13609         object_type_id = QT_UINT8 (ptr);
13610         stream_type = QT_UINT8 (ptr + 1) >> 2;
13611         max_bitrate = QT_UINT32 (ptr + 5);
13612         avg_bitrate = QT_UINT32 (ptr + 9);
13613         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13614         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13615         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13616         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13617         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13618         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13619           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13620               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13621         }
13622         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13623           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13624               avg_bitrate, NULL);
13625         }
13626         ptr += 13;
13627         break;
13628       }
13629       case DECODER_SPECIFIC_INFO_TAG:
13630         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13631         if (object_type_id == 0xe0 && len == 0x40) {
13632           guint8 *data;
13633           GstStructure *s;
13634           guint32 clut[16];
13635           gint i;
13636
13637           GST_DEBUG_OBJECT (qtdemux,
13638               "Have VOBSUB palette. Creating palette event");
13639           /* move to decConfigDescr data and read palette */
13640           data = ptr;
13641           for (i = 0; i < 16; i++) {
13642             clut[i] = QT_UINT32 (data);
13643             data += 4;
13644           }
13645
13646           s = gst_structure_new ("application/x-gst-dvd", "event",
13647               G_TYPE_STRING, "dvd-spu-clut-change",
13648               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13649               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13650               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13651               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13652               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13653               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13654               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13655               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13656               NULL);
13657
13658           /* store event and trigger custom processing */
13659           stream->pending_event =
13660               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13661         } else {
13662           /* Generic codec_data handler puts it on the caps */
13663           data_ptr = ptr;
13664           data_len = len;
13665         }
13666
13667         ptr += len;
13668         break;
13669       case SL_CONFIG_DESC_TAG:
13670         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13671         ptr += 1;
13672         break;
13673       default:
13674         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13675             tag);
13676         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13677         ptr += len;
13678         break;
13679     }
13680   }
13681
13682   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13683    * in use, and should also be used to override some other parameters for some
13684    * codecs. */
13685   switch (object_type_id) {
13686     case 0x20:                 /* MPEG-4 */
13687       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13688        * profile_and_level_indication */
13689       if (data_ptr != NULL && data_len >= 5 &&
13690           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13691         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13692             data_ptr + 4, data_len - 4);
13693       }
13694       break;                    /* Nothing special needed here */
13695     case 0x21:                 /* H.264 */
13696       codec_name = "H.264 / AVC";
13697       caps = gst_caps_new_simple ("video/x-h264",
13698           "stream-format", G_TYPE_STRING, "avc",
13699           "alignment", G_TYPE_STRING, "au", NULL);
13700       break;
13701     case 0x40:                 /* AAC (any) */
13702     case 0x66:                 /* AAC Main */
13703     case 0x67:                 /* AAC LC */
13704     case 0x68:                 /* AAC SSR */
13705       /* Override channels and rate based on the codec_data, as it's often
13706        * wrong. */
13707       /* Only do so for basic setup without HE-AAC extension */
13708       if (data_ptr && data_len == 2) {
13709         guint channels, rate;
13710
13711         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13712         if (channels > 0)
13713           entry->n_channels = channels;
13714
13715         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13716         if (rate > 0)
13717           entry->rate = rate;
13718       }
13719
13720       /* Set level and profile if possible */
13721       if (data_ptr != NULL && data_len >= 2) {
13722         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13723             data_ptr, data_len);
13724       } else {
13725         const gchar *profile_str = NULL;
13726         GstBuffer *buffer;
13727         GstMapInfo map;
13728         guint8 *codec_data;
13729         gint rate_idx, profile;
13730
13731         /* No codec_data, let's invent something.
13732          * FIXME: This is wrong for SBR! */
13733
13734         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13735
13736         buffer = gst_buffer_new_and_alloc (2);
13737         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13738         codec_data = map.data;
13739
13740         rate_idx =
13741             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13742             (stream)->rate);
13743
13744         switch (object_type_id) {
13745           case 0x66:
13746             profile_str = "main";
13747             profile = 0;
13748             break;
13749           case 0x67:
13750             profile_str = "lc";
13751             profile = 1;
13752             break;
13753           case 0x68:
13754             profile_str = "ssr";
13755             profile = 2;
13756             break;
13757           default:
13758             profile = 3;
13759             break;
13760         }
13761
13762         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13763         codec_data[1] =
13764             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13765
13766         gst_buffer_unmap (buffer, &map);
13767         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13768             GST_TYPE_BUFFER, buffer, NULL);
13769         gst_buffer_unref (buffer);
13770
13771         if (profile_str) {
13772           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13773               G_TYPE_STRING, profile_str, NULL);
13774         }
13775       }
13776       break;
13777     case 0x60:                 /* MPEG-2, various profiles */
13778     case 0x61:
13779     case 0x62:
13780     case 0x63:
13781     case 0x64:
13782     case 0x65:
13783       codec_name = "MPEG-2 video";
13784       caps = gst_caps_new_simple ("video/mpeg",
13785           "mpegversion", G_TYPE_INT, 2,
13786           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13787       break;
13788     case 0x69:                 /* MPEG-2 BC audio */
13789     case 0x6B:                 /* MPEG-1 audio */
13790       caps = gst_caps_new_simple ("audio/mpeg",
13791           "mpegversion", G_TYPE_INT, 1, NULL);
13792       codec_name = "MPEG-1 audio";
13793       break;
13794     case 0x6A:                 /* MPEG-1 */
13795       codec_name = "MPEG-1 video";
13796       caps = gst_caps_new_simple ("video/mpeg",
13797           "mpegversion", G_TYPE_INT, 1,
13798           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13799       break;
13800     case 0x6C:                 /* MJPEG */
13801       caps =
13802           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13803           NULL);
13804       codec_name = "Motion-JPEG";
13805       break;
13806     case 0x6D:                 /* PNG */
13807       caps =
13808           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13809           NULL);
13810       codec_name = "PNG still images";
13811       break;
13812     case 0x6E:                 /* JPEG2000 */
13813       codec_name = "JPEG-2000";
13814       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13815       break;
13816     case 0xA4:                 /* Dirac */
13817       codec_name = "Dirac";
13818       caps = gst_caps_new_empty_simple ("video/x-dirac");
13819       break;
13820     case 0xA5:                 /* AC3 */
13821       codec_name = "AC-3 audio";
13822       caps = gst_caps_new_simple ("audio/x-ac3",
13823           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13824       break;
13825     case 0xA9:                 /* AC3 */
13826       codec_name = "DTS audio";
13827       caps = gst_caps_new_simple ("audio/x-dts",
13828           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13829       break;
13830     case 0xDD:
13831       if (stream_type == 0x05 && data_ptr) {
13832         GList *headers =
13833             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
13834         if (headers) {
13835           GList *tmp;
13836           GValue arr_val = G_VALUE_INIT;
13837           GValue buf_val = G_VALUE_INIT;
13838           GstStructure *s;
13839
13840           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
13841           codec_name = "Vorbis";
13842           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
13843           g_value_init (&arr_val, GST_TYPE_ARRAY);
13844           g_value_init (&buf_val, GST_TYPE_BUFFER);
13845           for (tmp = headers; tmp; tmp = tmp->next) {
13846             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
13847             gst_value_array_append_value (&arr_val, &buf_val);
13848           }
13849           s = gst_caps_get_structure (caps, 0);
13850           gst_structure_take_value (s, "streamheader", &arr_val);
13851           g_value_unset (&buf_val);
13852           g_list_free (headers);
13853
13854           data_ptr = NULL;
13855           data_len = 0;
13856         }
13857       }
13858       break;
13859     case 0xE1:                 /* QCELP */
13860       /* QCELP, the codec_data is a riff tag (little endian) with
13861        * 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). */
13862       caps = gst_caps_new_empty_simple ("audio/qcelp");
13863       codec_name = "QCELP";
13864       break;
13865     default:
13866       break;
13867   }
13868
13869   /* If we have a replacement caps, then change our caps for this stream */
13870   if (caps) {
13871     gst_caps_unref (entry->caps);
13872     entry->caps = caps;
13873   }
13874
13875   if (codec_name && list)
13876     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13877         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13878
13879   /* Add the codec_data attribute to caps, if we have it */
13880   if (data_ptr) {
13881     GstBuffer *buffer;
13882
13883     buffer = gst_buffer_new_and_alloc (data_len);
13884     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13885
13886     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13887     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13888
13889     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13890         buffer, NULL);
13891     gst_buffer_unref (buffer);
13892   }
13893
13894 }
13895
13896 static inline GstCaps *
13897 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13898 {
13899   GstCaps *caps;
13900   guint i;
13901   char *s, fourstr[5];
13902
13903   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13904   for (i = 0; i < 4; i++) {
13905     if (!g_ascii_isalnum (fourstr[i]))
13906       fourstr[i] = '_';
13907   }
13908   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13909   caps = gst_caps_new_empty_simple (s);
13910   g_free (s);
13911   return caps;
13912 }
13913
13914 #define _codec(name) \
13915   do { \
13916     if (codec_name) { \
13917       *codec_name = g_strdup (name); \
13918     } \
13919   } while (0)
13920
13921 static GstCaps *
13922 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13923     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13924     const guint8 * stsd_entry_data, gchar ** codec_name)
13925 {
13926   GstCaps *caps = NULL;
13927   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13928
13929   switch (fourcc) {
13930     case FOURCC_png:
13931       _codec ("PNG still images");
13932       caps = gst_caps_new_empty_simple ("image/png");
13933       break;
13934     case FOURCC_jpeg:
13935       _codec ("JPEG still images");
13936       caps =
13937           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13938           NULL);
13939       break;
13940     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13941     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13942     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13943     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13944       _codec ("Motion-JPEG");
13945       caps =
13946           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13947           NULL);
13948       break;
13949     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13950       _codec ("Motion-JPEG format B");
13951       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13952       break;
13953     case FOURCC_mjp2:
13954       _codec ("JPEG-2000");
13955       /* override to what it should be according to spec, avoid palette_data */
13956       entry->bits_per_sample = 24;
13957       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13958       break;
13959     case FOURCC_SVQ3:
13960       _codec ("Sorensen video v.3");
13961       caps = gst_caps_new_simple ("video/x-svq",
13962           "svqversion", G_TYPE_INT, 3, NULL);
13963       break;
13964     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13965     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13966       _codec ("Sorensen video v.1");
13967       caps = gst_caps_new_simple ("video/x-svq",
13968           "svqversion", G_TYPE_INT, 1, NULL);
13969       break;
13970     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13971       caps = gst_caps_new_empty_simple ("video/x-raw");
13972       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13973       _codec ("Windows Raw RGB");
13974       stream->alignment = 32;
13975       break;
13976     case FOURCC_raw_:
13977     {
13978       guint16 bps;
13979
13980       bps = QT_UINT16 (stsd_entry_data + 82);
13981       switch (bps) {
13982         case 15:
13983           format = GST_VIDEO_FORMAT_RGB15;
13984           break;
13985         case 16:
13986           format = GST_VIDEO_FORMAT_RGB16;
13987           break;
13988         case 24:
13989           format = GST_VIDEO_FORMAT_RGB;
13990           break;
13991         case 32:
13992           format = GST_VIDEO_FORMAT_ARGB;
13993           break;
13994         default:
13995           /* unknown */
13996           break;
13997       }
13998       break;
13999     }
14000     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14001       format = GST_VIDEO_FORMAT_I420;
14002       break;
14003     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14004     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14005       format = GST_VIDEO_FORMAT_I420;
14006       break;
14007     case FOURCC_2vuy:
14008     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14009       format = GST_VIDEO_FORMAT_UYVY;
14010       break;
14011     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14012       format = GST_VIDEO_FORMAT_v308;
14013       break;
14014     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14015       format = GST_VIDEO_FORMAT_v216;
14016       break;
14017     case FOURCC_v210:
14018       format = GST_VIDEO_FORMAT_v210;
14019       break;
14020     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14021       format = GST_VIDEO_FORMAT_r210;
14022       break;
14023       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14024          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14025          format = GST_VIDEO_FORMAT_v410;
14026          break;
14027        */
14028       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14029        * but different order than AYUV
14030        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14031        format = GST_VIDEO_FORMAT_v408;
14032        break;
14033        */
14034     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14035     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14036       _codec ("MPEG-1 video");
14037       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14038           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14039       break;
14040     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14041     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14042     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14043     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14044     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14045     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14046     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14047     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14048     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14049     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14050     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14051     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14052     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14053     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14054     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14055     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14056     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14057     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14058     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14059     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14060     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14061     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14062     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14063     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14064     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14065     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14066     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14067     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14068     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14069     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14070     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14071     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14072     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14073     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14074     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14075     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14076     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14077     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14078     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14079     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14080     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14081     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14082     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14083     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14084     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14085     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14086     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14087       _codec ("MPEG-2 video");
14088       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14089           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14090       break;
14091     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14092       _codec ("GIF still images");
14093       caps = gst_caps_new_empty_simple ("image/gif");
14094       break;
14095     case FOURCC_h263:
14096     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14097     case FOURCC_s263:
14098     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14099       _codec ("H.263");
14100       /* ffmpeg uses the height/width props, don't know why */
14101       caps = gst_caps_new_simple ("video/x-h263",
14102           "variant", G_TYPE_STRING, "itu", NULL);
14103       break;
14104     case FOURCC_mp4v:
14105     case FOURCC_MP4V:
14106       _codec ("MPEG-4 video");
14107       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14108           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14109       break;
14110     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14111     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14112       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14113       caps = gst_caps_new_simple ("video/x-msmpeg",
14114           "msmpegversion", G_TYPE_INT, 43, NULL);
14115       break;
14116     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14117       _codec ("DivX 3");
14118       caps = gst_caps_new_simple ("video/x-divx",
14119           "divxversion", G_TYPE_INT, 3, NULL);
14120       break;
14121     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14122     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14123       _codec ("DivX 4");
14124       caps = gst_caps_new_simple ("video/x-divx",
14125           "divxversion", G_TYPE_INT, 4, NULL);
14126       break;
14127     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14128       _codec ("DivX 5");
14129       caps = gst_caps_new_simple ("video/x-divx",
14130           "divxversion", G_TYPE_INT, 5, NULL);
14131       break;
14132
14133     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14134       _codec ("FFV1");
14135       caps = gst_caps_new_simple ("video/x-ffv",
14136           "ffvversion", G_TYPE_INT, 1, NULL);
14137       break;
14138
14139     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14140     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14141     case FOURCC_XVID:
14142     case FOURCC_xvid:
14143     case FOURCC_FMP4:
14144     case FOURCC_fmp4:
14145     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14146       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14147           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14148       _codec ("MPEG-4");
14149       break;
14150
14151     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14152       _codec ("Cinepak");
14153       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14154       break;
14155     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14156       _codec ("Apple QuickDraw");
14157       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14158       break;
14159     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14160       _codec ("Apple video");
14161       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14162       break;
14163     case FOURCC_H264:
14164     case FOURCC_avc1:
14165       _codec ("H.264 / AVC");
14166       caps = gst_caps_new_simple ("video/x-h264",
14167           "stream-format", G_TYPE_STRING, "avc",
14168           "alignment", G_TYPE_STRING, "au", NULL);
14169       break;
14170     case FOURCC_avc3:
14171       _codec ("H.264 / AVC");
14172       caps = gst_caps_new_simple ("video/x-h264",
14173           "stream-format", G_TYPE_STRING, "avc3",
14174           "alignment", G_TYPE_STRING, "au", NULL);
14175       break;
14176     case FOURCC_H265:
14177     case FOURCC_hvc1:
14178       _codec ("H.265 / HEVC");
14179       caps = gst_caps_new_simple ("video/x-h265",
14180           "stream-format", G_TYPE_STRING, "hvc1",
14181           "alignment", G_TYPE_STRING, "au", NULL);
14182       break;
14183     case FOURCC_hev1:
14184       _codec ("H.265 / HEVC");
14185       caps = gst_caps_new_simple ("video/x-h265",
14186           "stream-format", G_TYPE_STRING, "hev1",
14187           "alignment", G_TYPE_STRING, "au", NULL);
14188       break;
14189     case FOURCC_rle_:
14190       _codec ("Run-length encoding");
14191       caps = gst_caps_new_simple ("video/x-rle",
14192           "layout", G_TYPE_STRING, "quicktime", NULL);
14193       break;
14194     case FOURCC_WRLE:
14195       _codec ("Run-length encoding");
14196       caps = gst_caps_new_simple ("video/x-rle",
14197           "layout", G_TYPE_STRING, "microsoft", NULL);
14198       break;
14199     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14200     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14201       _codec ("Indeo Video 3");
14202       caps = gst_caps_new_simple ("video/x-indeo",
14203           "indeoversion", G_TYPE_INT, 3, NULL);
14204       break;
14205     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14206     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14207       _codec ("Intel Video 4");
14208       caps = gst_caps_new_simple ("video/x-indeo",
14209           "indeoversion", G_TYPE_INT, 4, NULL);
14210       break;
14211     case FOURCC_dvcp:
14212     case FOURCC_dvc_:
14213     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14214     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14215     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14216     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14217     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14218     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14219       _codec ("DV Video");
14220       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14221           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14222       break;
14223     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14224     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14225       _codec ("DVCPro50 Video");
14226       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14227           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14228       break;
14229     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14230     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14231       _codec ("DVCProHD Video");
14232       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14233           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14234       break;
14235     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14236       _codec ("Apple Graphics (SMC)");
14237       caps = gst_caps_new_empty_simple ("video/x-smc");
14238       break;
14239     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14240       _codec ("VP3");
14241       caps = gst_caps_new_empty_simple ("video/x-vp3");
14242       break;
14243     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14244       _codec ("VP6 Flash");
14245       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14246       break;
14247     case FOURCC_XiTh:
14248       _codec ("Theora");
14249       caps = gst_caps_new_empty_simple ("video/x-theora");
14250       /* theora uses one byte of padding in the data stream because it does not
14251        * allow 0 sized packets while theora does */
14252       entry->padding = 1;
14253       break;
14254     case FOURCC_drac:
14255       _codec ("Dirac");
14256       caps = gst_caps_new_empty_simple ("video/x-dirac");
14257       break;
14258     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14259       _codec ("TIFF still images");
14260       caps = gst_caps_new_empty_simple ("image/tiff");
14261       break;
14262     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14263       _codec ("Apple Intermediate Codec");
14264       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14265       break;
14266     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14267       _codec ("AVID DNxHD");
14268       caps = gst_caps_from_string ("video/x-dnxhd");
14269       break;
14270     case FOURCC_VP80:
14271     case FOURCC_vp08:
14272       _codec ("On2 VP8");
14273       caps = gst_caps_from_string ("video/x-vp8");
14274       break;
14275     case FOURCC_vp09:
14276       _codec ("Google VP9");
14277       caps = gst_caps_from_string ("video/x-vp9");
14278       break;
14279     case FOURCC_apcs:
14280       _codec ("Apple ProRes LT");
14281       caps =
14282           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14283           NULL);
14284       break;
14285     case FOURCC_apch:
14286       _codec ("Apple ProRes HQ");
14287       caps =
14288           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14289           NULL);
14290       break;
14291     case FOURCC_apcn:
14292       _codec ("Apple ProRes");
14293       caps =
14294           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14295           "standard", NULL);
14296       break;
14297     case FOURCC_apco:
14298       _codec ("Apple ProRes Proxy");
14299       caps =
14300           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14301           "proxy", NULL);
14302       break;
14303     case FOURCC_ap4h:
14304       _codec ("Apple ProRes 4444");
14305       caps =
14306           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14307           "4444", NULL);
14308       break;
14309     case FOURCC_ap4x:
14310       _codec ("Apple ProRes 4444 XQ");
14311       caps =
14312           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14313           "4444xq", NULL);
14314       break;
14315     case FOURCC_cfhd:
14316       _codec ("GoPro CineForm");
14317       caps = gst_caps_from_string ("video/x-cineform");
14318       break;
14319     case FOURCC_vc_1:
14320     case FOURCC_ovc1:
14321       _codec ("VC-1");
14322       caps = gst_caps_new_simple ("video/x-wmv",
14323           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14324       break;
14325     case FOURCC_av01:
14326       _codec ("AV1");
14327       caps = gst_caps_new_empty_simple ("video/x-av1");
14328       break;
14329     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14330     default:
14331     {
14332       caps = _get_unknown_codec_name ("video", fourcc);
14333       break;
14334     }
14335   }
14336
14337   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14338     GstVideoInfo info;
14339
14340     gst_video_info_init (&info);
14341     gst_video_info_set_format (&info, format, entry->width, entry->height);
14342
14343     caps = gst_video_info_to_caps (&info);
14344     *codec_name = gst_pb_utils_get_codec_description (caps);
14345
14346     /* enable clipping for raw video streams */
14347     stream->need_clip = TRUE;
14348     stream->alignment = 32;
14349   }
14350
14351   return caps;
14352 }
14353
14354 static guint
14355 round_up_pow2 (guint n)
14356 {
14357   n = n - 1;
14358   n = n | (n >> 1);
14359   n = n | (n >> 2);
14360   n = n | (n >> 4);
14361   n = n | (n >> 8);
14362   n = n | (n >> 16);
14363   return n + 1;
14364 }
14365
14366 static GstCaps *
14367 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14368     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14369     int len, gchar ** codec_name)
14370 {
14371   GstCaps *caps;
14372   const GstStructure *s;
14373   const gchar *name;
14374   gint endian = 0;
14375   GstAudioFormat format = 0;
14376   gint depth;
14377
14378   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14379
14380   depth = entry->bytes_per_packet * 8;
14381
14382   switch (fourcc) {
14383     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14384     case FOURCC_raw_:
14385       /* 8-bit audio is unsigned */
14386       if (depth == 8)
14387         format = GST_AUDIO_FORMAT_U8;
14388       /* otherwise it's signed and big-endian just like 'twos' */
14389     case FOURCC_twos:
14390       endian = G_BIG_ENDIAN;
14391       /* fall-through */
14392     case FOURCC_sowt:
14393     {
14394       gchar *str;
14395
14396       if (!endian)
14397         endian = G_LITTLE_ENDIAN;
14398
14399       if (!format)
14400         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14401
14402       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14403       _codec (str);
14404       g_free (str);
14405
14406       caps = gst_caps_new_simple ("audio/x-raw",
14407           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14408           "layout", G_TYPE_STRING, "interleaved", NULL);
14409       stream->alignment = GST_ROUND_UP_8 (depth);
14410       stream->alignment = round_up_pow2 (stream->alignment);
14411       break;
14412     }
14413     case FOURCC_fl64:
14414       _codec ("Raw 64-bit floating-point audio");
14415       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14416        * endian later */
14417       caps = gst_caps_new_simple ("audio/x-raw",
14418           "format", G_TYPE_STRING, "F64BE",
14419           "layout", G_TYPE_STRING, "interleaved", NULL);
14420       stream->alignment = 8;
14421       break;
14422     case FOURCC_fl32:
14423       _codec ("Raw 32-bit floating-point audio");
14424       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14425        * endian later */
14426       caps = gst_caps_new_simple ("audio/x-raw",
14427           "format", G_TYPE_STRING, "F32BE",
14428           "layout", G_TYPE_STRING, "interleaved", NULL);
14429       stream->alignment = 4;
14430       break;
14431     case FOURCC_in24:
14432       _codec ("Raw 24-bit PCM audio");
14433       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14434        * endian later */
14435       caps = gst_caps_new_simple ("audio/x-raw",
14436           "format", G_TYPE_STRING, "S24BE",
14437           "layout", G_TYPE_STRING, "interleaved", NULL);
14438       stream->alignment = 4;
14439       break;
14440     case FOURCC_in32:
14441       _codec ("Raw 32-bit PCM audio");
14442       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14443        * endian later */
14444       caps = gst_caps_new_simple ("audio/x-raw",
14445           "format", G_TYPE_STRING, "S32BE",
14446           "layout", G_TYPE_STRING, "interleaved", NULL);
14447       stream->alignment = 4;
14448       break;
14449     case FOURCC_s16l:
14450       _codec ("Raw 16-bit PCM audio");
14451       caps = gst_caps_new_simple ("audio/x-raw",
14452           "format", G_TYPE_STRING, "S16LE",
14453           "layout", G_TYPE_STRING, "interleaved", NULL);
14454       stream->alignment = 2;
14455       break;
14456     case FOURCC_ulaw:
14457       _codec ("Mu-law audio");
14458       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14459       break;
14460     case FOURCC_alaw:
14461       _codec ("A-law audio");
14462       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14463       break;
14464     case 0x0200736d:
14465     case 0x6d730002:
14466       _codec ("Microsoft ADPCM");
14467       /* Microsoft ADPCM-ACM code 2 */
14468       caps = gst_caps_new_simple ("audio/x-adpcm",
14469           "layout", G_TYPE_STRING, "microsoft", NULL);
14470       break;
14471     case 0x1100736d:
14472     case 0x6d730011:
14473       _codec ("DVI/IMA ADPCM");
14474       caps = gst_caps_new_simple ("audio/x-adpcm",
14475           "layout", G_TYPE_STRING, "dvi", NULL);
14476       break;
14477     case 0x1700736d:
14478     case 0x6d730017:
14479       _codec ("DVI/Intel IMA ADPCM");
14480       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14481       caps = gst_caps_new_simple ("audio/x-adpcm",
14482           "layout", G_TYPE_STRING, "quicktime", NULL);
14483       break;
14484     case 0x5500736d:
14485     case 0x6d730055:
14486       /* MPEG layer 3, CBR only (pre QT4.1) */
14487     case FOURCC__mp3:
14488     case FOURCC_mp3_:
14489       _codec ("MPEG-1 layer 3");
14490       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14491       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14492           "mpegversion", G_TYPE_INT, 1, NULL);
14493       break;
14494     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14495       _codec ("MPEG-1 layer 2");
14496       /* MPEG layer 2 */
14497       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14498           "mpegversion", G_TYPE_INT, 1, NULL);
14499       break;
14500     case 0x20736d:
14501     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14502       _codec ("EAC-3 audio");
14503       caps = gst_caps_new_simple ("audio/x-eac3",
14504           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14505       entry->sampled = TRUE;
14506       break;
14507     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14508     case FOURCC_ac_3:
14509       _codec ("AC-3 audio");
14510       caps = gst_caps_new_simple ("audio/x-ac3",
14511           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14512       entry->sampled = TRUE;
14513       break;
14514     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14515     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14516       _codec ("DTS audio");
14517       caps = gst_caps_new_simple ("audio/x-dts",
14518           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14519       entry->sampled = TRUE;
14520       break;
14521     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14522     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14523       _codec ("DTS-HD audio");
14524       caps = gst_caps_new_simple ("audio/x-dts",
14525           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14526       entry->sampled = TRUE;
14527       break;
14528     case FOURCC_MAC3:
14529       _codec ("MACE-3");
14530       caps = gst_caps_new_simple ("audio/x-mace",
14531           "maceversion", G_TYPE_INT, 3, NULL);
14532       break;
14533     case FOURCC_MAC6:
14534       _codec ("MACE-6");
14535       caps = gst_caps_new_simple ("audio/x-mace",
14536           "maceversion", G_TYPE_INT, 6, NULL);
14537       break;
14538     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14539       /* ogg/vorbis */
14540       caps = gst_caps_new_empty_simple ("application/ogg");
14541       break;
14542     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14543       _codec ("DV audio");
14544       caps = gst_caps_new_empty_simple ("audio/x-dv");
14545       break;
14546     case FOURCC_mp4a:
14547       _codec ("MPEG-4 AAC audio");
14548       caps = gst_caps_new_simple ("audio/mpeg",
14549           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14550           "stream-format", G_TYPE_STRING, "raw", NULL);
14551       break;
14552     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14553       _codec ("QDesign Music");
14554       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14555       break;
14556     case FOURCC_QDM2:
14557       _codec ("QDesign Music v.2");
14558       /* FIXME: QDesign music version 2 (no constant) */
14559       if (FALSE && data) {
14560         caps = gst_caps_new_simple ("audio/x-qdm2",
14561             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14562             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14563             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14564       } else {
14565         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14566       }
14567       break;
14568     case FOURCC_agsm:
14569       _codec ("GSM audio");
14570       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14571       break;
14572     case FOURCC_samr:
14573       _codec ("AMR audio");
14574       caps = gst_caps_new_empty_simple ("audio/AMR");
14575       break;
14576     case FOURCC_sawb:
14577       _codec ("AMR-WB audio");
14578       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14579       break;
14580     case FOURCC_ima4:
14581       _codec ("Quicktime IMA ADPCM");
14582       caps = gst_caps_new_simple ("audio/x-adpcm",
14583           "layout", G_TYPE_STRING, "quicktime", NULL);
14584       break;
14585     case FOURCC_alac:
14586       _codec ("Apple lossless audio");
14587       caps = gst_caps_new_empty_simple ("audio/x-alac");
14588       break;
14589     case FOURCC_fLaC:
14590       _codec ("Free Lossless Audio Codec");
14591       caps = gst_caps_new_simple ("audio/x-flac",
14592           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14593       break;
14594     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14595       _codec ("QualComm PureVoice");
14596       caps = gst_caps_from_string ("audio/qcelp");
14597       break;
14598     case FOURCC_wma_:
14599     case FOURCC_owma:
14600       _codec ("WMA");
14601       caps = gst_caps_new_empty_simple ("audio/x-wma");
14602       break;
14603     case FOURCC_opus:
14604       _codec ("Opus");
14605       caps = gst_caps_new_empty_simple ("audio/x-opus");
14606       break;
14607     case FOURCC_lpcm:
14608     {
14609       guint32 flags = 0;
14610       guint32 depth = 0;
14611       guint32 width = 0;
14612       GstAudioFormat format;
14613       enum
14614       {
14615         FLAG_IS_FLOAT = 0x1,
14616         FLAG_IS_BIG_ENDIAN = 0x2,
14617         FLAG_IS_SIGNED = 0x4,
14618         FLAG_IS_PACKED = 0x8,
14619         FLAG_IS_ALIGNED_HIGH = 0x10,
14620         FLAG_IS_NON_INTERLEAVED = 0x20
14621       };
14622       _codec ("Raw LPCM audio");
14623
14624       if (data && len >= 36) {
14625         depth = QT_UINT32 (data + 24);
14626         flags = QT_UINT32 (data + 28);
14627         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14628       }
14629       if ((flags & FLAG_IS_FLOAT) == 0) {
14630         if (depth == 0)
14631           depth = 16;
14632         if (width == 0)
14633           width = 16;
14634         if ((flags & FLAG_IS_ALIGNED_HIGH))
14635           depth = width;
14636
14637         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14638             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14639             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14640         caps = gst_caps_new_simple ("audio/x-raw",
14641             "format", G_TYPE_STRING,
14642             format !=
14643             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14644             "UNKNOWN", "layout", G_TYPE_STRING,
14645             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14646             "interleaved", NULL);
14647         stream->alignment = GST_ROUND_UP_8 (depth);
14648         stream->alignment = round_up_pow2 (stream->alignment);
14649       } else {
14650         if (width == 0)
14651           width = 32;
14652         if (width == 64) {
14653           if (flags & FLAG_IS_BIG_ENDIAN)
14654             format = GST_AUDIO_FORMAT_F64BE;
14655           else
14656             format = GST_AUDIO_FORMAT_F64LE;
14657         } else {
14658           if (flags & FLAG_IS_BIG_ENDIAN)
14659             format = GST_AUDIO_FORMAT_F32BE;
14660           else
14661             format = GST_AUDIO_FORMAT_F32LE;
14662         }
14663         caps = gst_caps_new_simple ("audio/x-raw",
14664             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14665             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14666             "non-interleaved" : "interleaved", NULL);
14667         stream->alignment = width / 8;
14668       }
14669       break;
14670     }
14671     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14672     {
14673       _codec ("AC4");
14674       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14675       break;
14676     }
14677     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14678       /* ? */
14679     default:
14680     {
14681       caps = _get_unknown_codec_name ("audio", fourcc);
14682       break;
14683     }
14684   }
14685
14686   if (caps) {
14687     GstCaps *templ_caps =
14688         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14689     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14690     gst_caps_unref (caps);
14691     gst_caps_unref (templ_caps);
14692     caps = intersection;
14693   }
14694
14695   /* enable clipping for raw audio streams */
14696   s = gst_caps_get_structure (caps, 0);
14697   name = gst_structure_get_name (s);
14698   if (g_str_has_prefix (name, "audio/x-raw")) {
14699     stream->need_clip = TRUE;
14700     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
14701     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14702     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
14703         stream->max_buffer_size);
14704   }
14705   return caps;
14706 }
14707
14708 static GstCaps *
14709 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14710     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14711     const guint8 * stsd_entry_data, gchar ** codec_name)
14712 {
14713   GstCaps *caps;
14714
14715   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14716
14717   switch (fourcc) {
14718     case FOURCC_mp4s:
14719       _codec ("DVD subtitle");
14720       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14721       stream->need_process = TRUE;
14722       break;
14723     case FOURCC_text:
14724       _codec ("Quicktime timed text");
14725       goto text;
14726     case FOURCC_tx3g:
14727       _codec ("3GPP timed text");
14728     text:
14729       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14730           "utf8", NULL);
14731       /* actual text piece needs to be extracted */
14732       stream->need_process = TRUE;
14733       break;
14734     case FOURCC_stpp:
14735       _codec ("XML subtitles");
14736       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14737       break;
14738     case FOURCC_c608:
14739       _codec ("CEA 608 Closed Caption");
14740       caps =
14741           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
14742           G_TYPE_STRING, "s334-1a", NULL);
14743       stream->need_process = TRUE;
14744       stream->need_split = TRUE;
14745       break;
14746     case FOURCC_c708:
14747       _codec ("CEA 708 Closed Caption");
14748       caps =
14749           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
14750           G_TYPE_STRING, "cdp", NULL);
14751       stream->need_process = TRUE;
14752       break;
14753
14754     default:
14755     {
14756       caps = _get_unknown_codec_name ("text", fourcc);
14757       break;
14758     }
14759   }
14760   return caps;
14761 }
14762
14763 static GstCaps *
14764 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14765     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14766     const guint8 * stsd_entry_data, gchar ** codec_name)
14767 {
14768   GstCaps *caps;
14769
14770   switch (fourcc) {
14771     case FOURCC_m1v:
14772       _codec ("MPEG 1 video");
14773       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14774           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14775       break;
14776     default:
14777       caps = NULL;
14778       break;
14779   }
14780   return caps;
14781 }
14782
14783 static void
14784 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14785     const gchar * system_id)
14786 {
14787   gint i;
14788
14789   if (!qtdemux->protection_system_ids)
14790     qtdemux->protection_system_ids =
14791         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14792   /* Check whether we already have an entry for this system ID. */
14793   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14794     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14795     if (g_ascii_strcasecmp (system_id, id) == 0) {
14796       return;
14797     }
14798   }
14799   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14800   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14801           -1));
14802 }