qtdemux: Don't free cslg data that we don't own on corrupt files
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  * @title: qtdemux
33  *
34  * Demuxes a .mov file into raw or compressed audio and/or video streams.
35  *
36  * This element supports both push and pull-based scheduling, depending on the
37  * capabilities of the upstream elements.
38  *
39  * ## Example launch line
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  *
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "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 "gstisomp4elements.h"
63 #include "qtatomparser.h"
64 #include "qtdemux_types.h"
65 #include "qtdemux_dump.h"
66 #include "fourcc.h"
67 #include "descriptors.h"
68 #include "qtdemux_lang.h"
69 #include "qtdemux.h"
70 #include "qtpalette.h"
71 #include "qtdemux_tags.h"
72 #include "qtdemux_tree.h"
73 #include "qtdemux-webvtt.h"
74
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (32*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
104 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
105 #define QTDEMUX_NTH_STREAM(demux,idx) \
106    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
107 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
108    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
109
110 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
111
112 GST_DEBUG_CATEGORY (qtdemux_debug);
113 #define GST_CAT_DEFAULT qtdemux_debug
114
115 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
116 typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
117
118 /* Macros for converting to/from timescale */
119 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
120 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
121
122 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
123 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
124
125 /* timestamp is the DTS */
126 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
127 /* timestamp + offset + cslg_shift is the outgoing PTS */
128 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
129 /* timestamp + offset is the PTS used for internal seek calculations */
130 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
131 /* timestamp + duration - dts is the duration */
132 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
133
134 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
135
136 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
137 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
138     GST_TRACE("Locking from thread %p", g_thread_self()); \
139     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
140     GST_TRACE("Locked from thread %p", g_thread_self()); \
141  } G_STMT_END
142
143 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
144     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
145     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
146  } G_STMT_END
147
148 /*
149  * Quicktime has tracks and segments. A track is a continuous piece of
150  * multimedia content. The track is not always played from start to finish but
151  * instead, pieces of the track are 'cut out' and played in sequence. This is
152  * what the segments do.
153  *
154  * Inside the track we have keyframes (K) and delta frames. The track has its
155  * own timing, which starts from 0 and extends to end. The position in the track
156  * is called the media_time.
157  *
158  * The segments now describe the pieces that should be played from this track
159  * and are basically tuples of media_time/duration/rate entries. We can have
160  * multiple segments and they are all played after one another. An example:
161  *
162  * segment 1: media_time: 1 second, duration: 1 second, rate 1
163  * segment 2: media_time: 3 second, duration: 2 second, rate 2
164  *
165  * To correctly play back this track, one must play: 1 second of media starting
166  * from media_time 1 followed by 2 seconds of media starting from media_time 3
167  * at a rate of 2.
168  *
169  * Each of the segments will be played at a specific time, the first segment at
170  * time 0, the second one after the duration of the first one, etc.. Note that
171  * the time in resulting playback is not identical to the media_time of the
172  * track anymore.
173  *
174  * Visually, assuming the track has 4 second of media_time:
175  *
176  *                (a)                   (b)          (c)              (d)
177  *         .-----------------------------------------------------------.
178  * track:  | K.....K.........K........K.......K.......K...........K... |
179  *         '-----------------------------------------------------------'
180  *         0              1              2              3              4
181  *           .------------^              ^   .----------^              ^
182  *          /              .-------------'  /       .------------------'
183  *         /              /          .-----'       /
184  *         .--------------.         .--------------.
185  *         | segment 1    |         | segment 2    |
186  *         '--------------'         '--------------'
187  *
188  * The challenge here is to cut out the right pieces of the track for each of
189  * the playback segments. This fortunately can easily be done with the SEGMENT
190  * events of GStreamer.
191  *
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193  * (a), in the above figure, but we must instruct it only to output the decoded
194  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
195  * position set to the time of the segment: 0.
196  *
197  * We then proceed to push data from keyframe (a) to frame (b). The decoder
198  * decodes but clips all before media_time 1.
199  *
200  * After finishing a segment, we push out a new SEGMENT event with the clipping
201  * boundaries of the new data.
202  *
203  * This is a good usecase for the GStreamer accumulated SEGMENT events.
204  */
205
206 struct _QtDemuxSegment
207 {
208   /* global time and duration, all gst time */
209   GstClockTime time;
210   GstClockTime stop_time;
211   GstClockTime duration;
212   /* media time of trak, all gst time */
213   GstClockTime media_start;
214   GstClockTime media_stop;
215   gdouble rate;
216   /* Media start time in trak timescale units */
217   guint32 trak_media_start;
218 };
219
220 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
221
222 /* Used with fragmented MP4 files (mfra atom) */
223 struct _QtDemuxRandomAccessEntry
224 {
225   GstClockTime ts;
226   guint64 moof_offset;
227 };
228
229
230 /* Contains properties and cryptographic info for a set of samples from a
231  * track protected using Common Encryption (cenc) */
232 struct _QtDemuxCencSampleSetInfo
233 {
234   GstStructure *default_properties;
235
236   /* @crypto_info holds one GstStructure per sample */
237   GPtrArray *crypto_info;
238 };
239
240 struct _QtDemuxAavdEncryptionInfo
241 {
242   GstStructure *default_properties;
243 };
244
245 static const gchar *
246 qt_demux_state_string (enum QtDemuxState state)
247 {
248   switch (state) {
249     case QTDEMUX_STATE_INITIAL:
250       return "<INITIAL>";
251     case QTDEMUX_STATE_HEADER:
252       return "<HEADER>";
253     case QTDEMUX_STATE_MOVIE:
254       return "<MOVIE>";
255     case QTDEMUX_STATE_BUFFER_MDAT:
256       return "<BUFFER_MDAT>";
257     default:
258       return "<UNKNOWN>";
259   }
260 }
261
262 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
263
264 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
265
266 static GstStaticPadTemplate gst_qtdemux_sink_template =
267     GST_STATIC_PAD_TEMPLATE ("sink",
268     GST_PAD_SINK,
269     GST_PAD_ALWAYS,
270     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
271         "application/x-3gp")
272     );
273
274 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
275 GST_STATIC_PAD_TEMPLATE ("video_%u",
276     GST_PAD_SRC,
277     GST_PAD_SOMETIMES,
278     GST_STATIC_CAPS_ANY);
279
280 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
281 GST_STATIC_PAD_TEMPLATE ("audio_%u",
282     GST_PAD_SRC,
283     GST_PAD_SOMETIMES,
284     GST_STATIC_CAPS_ANY);
285
286 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
287 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
288     GST_PAD_SRC,
289     GST_PAD_SOMETIMES,
290     GST_STATIC_CAPS_ANY);
291
292 #define gst_qtdemux_parent_class parent_class
293 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
294 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
295     GST_RANK_PRIMARY, GST_TYPE_QTDEMUX, isomp4_element_init (plugin));
296
297 static void gst_qtdemux_dispose (GObject * object);
298 static void gst_qtdemux_finalize (GObject * object);
299
300 static guint32
301 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
302     GstClockTime media_time);
303 static guint32
304 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
305     QtDemuxStream * str, gint64 media_offset);
306
307 #if 0
308 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
309 static GstIndex *gst_qtdemux_get_index (GstElement * element);
310 #endif
311 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
312     GstStateChange transition);
313 static void gst_qtdemux_set_context (GstElement * element,
314     GstContext * context);
315 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
316 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
317     GstObject * parent, GstPadMode mode, gboolean active);
318
319 static void gst_qtdemux_loop (GstPad * pad);
320 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
321     GstBuffer * inbuf);
322 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
323     GstEvent * event);
324 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
325     GstQuery * query);
326 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
327 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
328     QtDemuxStream * stream);
329 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
330     QtDemuxStream * stream);
331 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
332     gboolean force);
333
334 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
335
336 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
337     const guint8 * buffer, guint length);
338 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
339     const guint8 * buffer, guint length);
340 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
341
342 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
343     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
344     GstTagList * list);
345 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
346     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
347     const guint8 * stsd_entry_data, gchar ** codec_name);
348 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
349     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
350     const guint8 * data, int len, gchar ** codec_name);
351 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
352     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
353     gchar ** codec_name);
354 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
355     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
356     const guint8 * stsd_entry_data, gchar ** codec_name);
357
358 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
359     QtDemuxStream * stream, guint32 n);
360 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
361 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
362 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
363 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
364 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
365 static void qtdemux_do_allocation (QtDemuxStream * stream,
366     GstQTDemux * qtdemux);
367 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
368     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
369 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
370     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
371     GstClockTime * _start, GstClockTime * _stop);
372 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
373     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
374
375 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
376 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
377
378 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
379
380 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
381     QtDemuxStream * stream, guint sample_index);
382 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
383     const gchar * id);
384 static void qtdemux_gst_structure_free (GstStructure * gststructure);
385 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
386
387 static void
388 gst_qtdemux_class_init (GstQTDemuxClass * klass)
389 {
390   GObjectClass *gobject_class;
391   GstElementClass *gstelement_class;
392
393   gobject_class = (GObjectClass *) klass;
394   gstelement_class = (GstElementClass *) klass;
395
396   parent_class = g_type_class_peek_parent (klass);
397
398   gobject_class->dispose = gst_qtdemux_dispose;
399   gobject_class->finalize = gst_qtdemux_finalize;
400
401   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
402 #if 0
403   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
404   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
405 #endif
406   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
407
408   gst_tag_register_musicbrainz_tags ();
409
410   gst_element_class_add_static_pad_template (gstelement_class,
411       &gst_qtdemux_sink_template);
412   gst_element_class_add_static_pad_template (gstelement_class,
413       &gst_qtdemux_videosrc_template);
414   gst_element_class_add_static_pad_template (gstelement_class,
415       &gst_qtdemux_audiosrc_template);
416   gst_element_class_add_static_pad_template (gstelement_class,
417       &gst_qtdemux_subsrc_template);
418   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
419       "Codec/Demuxer",
420       "Demultiplex a QuickTime file into audio and video streams",
421       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
422
423   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
424   gst_riff_init ();
425 }
426
427 static void
428 gst_qtdemux_init (GstQTDemux * qtdemux)
429 {
430   qtdemux->sinkpad =
431       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
432   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
433   gst_pad_set_activatemode_function (qtdemux->sinkpad,
434       qtdemux_sink_activate_mode);
435   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
436   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
437   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
438   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
439
440   qtdemux->adapter = gst_adapter_new ();
441   g_queue_init (&qtdemux->protection_event_queue);
442   qtdemux->flowcombiner = gst_flow_combiner_new ();
443   g_mutex_init (&qtdemux->expose_lock);
444
445   qtdemux->active_streams = g_ptr_array_new_with_free_func
446       ((GDestroyNotify) gst_qtdemux_stream_unref);
447   qtdemux->old_streams = g_ptr_array_new_with_free_func
448       ((GDestroyNotify) gst_qtdemux_stream_unref);
449
450   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
451
452   gst_qtdemux_reset (qtdemux, TRUE);
453 }
454
455 static void
456 gst_qtdemux_finalize (GObject * object)
457 {
458   GstQTDemux *qtdemux = GST_QTDEMUX (object);
459
460   g_free (qtdemux->redirect_location);
461
462   G_OBJECT_CLASS (parent_class)->finalize (object);
463 }
464
465 static void
466 gst_qtdemux_dispose (GObject * object)
467 {
468   GstQTDemux *qtdemux = GST_QTDEMUX (object);
469
470   if (qtdemux->adapter) {
471     g_object_unref (G_OBJECT (qtdemux->adapter));
472     qtdemux->adapter = NULL;
473   }
474   gst_tag_list_unref (qtdemux->tag_list);
475   gst_flow_combiner_free (qtdemux->flowcombiner);
476   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
477       NULL);
478   g_queue_clear (&qtdemux->protection_event_queue);
479
480   g_free (qtdemux->cenc_aux_info_sizes);
481   qtdemux->cenc_aux_info_sizes = NULL;
482   g_mutex_clear (&qtdemux->expose_lock);
483
484   g_ptr_array_free (qtdemux->active_streams, TRUE);
485   g_ptr_array_free (qtdemux->old_streams, TRUE);
486
487   G_OBJECT_CLASS (parent_class)->dispose (object);
488 }
489
490 static void
491 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
492 {
493   if (qtdemux->redirect_location) {
494     GST_ELEMENT_ERROR_WITH_DETAILS (qtdemux, STREAM, DEMUX,
495         (_("This file contains no playable streams.")),
496         ("no known streams found, a redirect message has been posted"),
497         ("redirect-location", G_TYPE_STRING, qtdemux->redirect_location, NULL));
498   } else {
499     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
500         (_("This file contains no playable streams.")),
501         ("no known streams found"));
502   }
503 }
504
505 static GstBuffer *
506 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
507 {
508   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
509       mem, size, 0, size, mem, free_func);
510 }
511
512 static GstFlowReturn
513 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
514     GstBuffer ** buf)
515 {
516   GstFlowReturn flow;
517   GstMapInfo map;
518   gsize bsize;
519
520   if (G_UNLIKELY (size == 0)) {
521     GstFlowReturn ret;
522     GstBuffer *tmp = NULL;
523
524     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
525     if (ret != GST_FLOW_OK)
526       return ret;
527
528     gst_buffer_map (tmp, &map, GST_MAP_READ);
529     size = QT_UINT32 (map.data);
530     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
531
532     gst_buffer_unmap (tmp, &map);
533     gst_buffer_unref (tmp);
534   }
535
536   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
537   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
538     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
539       /* we're pulling header but already got most interesting bits,
540        * so never mind the rest (e.g. tags) (that much) */
541       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
542           size);
543       return GST_FLOW_EOS;
544     } else {
545       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
546           (_("This file is invalid and cannot be played.")),
547           ("atom has bogus size %" G_GUINT64_FORMAT, size));
548       return GST_FLOW_ERROR;
549     }
550   }
551
552   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
553
554   if (G_UNLIKELY (flow != GST_FLOW_OK))
555     return flow;
556
557   bsize = gst_buffer_get_size (*buf);
558   /* Catch short reads - we don't want any partial atoms */
559   if (G_UNLIKELY (bsize < size)) {
560     GST_WARNING_OBJECT (qtdemux,
561         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
562     gst_buffer_unref (*buf);
563     *buf = NULL;
564     return GST_FLOW_EOS;
565   }
566
567   return flow;
568 }
569
570 #if 1
571 static gboolean
572 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
573     GstFormat src_format, gint64 src_value, GstFormat dest_format,
574     gint64 * dest_value)
575 {
576   gboolean res = TRUE;
577   QtDemuxStream *stream = gst_pad_get_element_private (pad);
578   gint32 index;
579
580   if (stream->subtype != FOURCC_vide) {
581     res = FALSE;
582     goto done;
583   }
584
585   switch (src_format) {
586     case GST_FORMAT_TIME:
587       switch (dest_format) {
588         case GST_FORMAT_BYTES:{
589           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
590           if (-1 == index) {
591             res = FALSE;
592             goto done;
593           }
594
595           *dest_value = stream->samples[index].offset;
596
597           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
598               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
599               GST_TIME_ARGS (src_value), *dest_value);
600           break;
601         }
602         default:
603           res = FALSE;
604           break;
605       }
606       break;
607     case GST_FORMAT_BYTES:
608       switch (dest_format) {
609         case GST_FORMAT_TIME:{
610           index =
611               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
612               stream, src_value);
613
614           if (-1 == index) {
615             res = FALSE;
616             goto done;
617           }
618
619           *dest_value =
620               QTSTREAMTIME_TO_GSTTIME (stream,
621               stream->samples[index].timestamp);
622           GST_DEBUG_OBJECT (qtdemux,
623               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
624               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
625           break;
626         }
627         default:
628           res = FALSE;
629           break;
630       }
631       break;
632     default:
633       res = FALSE;
634       break;
635   }
636
637 done:
638   return res;
639 }
640 #endif
641
642 static gboolean
643 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
644 {
645   gboolean res = FALSE;
646
647   *duration = GST_CLOCK_TIME_NONE;
648
649   if (qtdemux->duration != 0 &&
650       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
651     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
652     res = TRUE;
653   } else {
654     *duration = GST_CLOCK_TIME_NONE;
655   }
656
657   return res;
658 }
659
660 static gboolean
661 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
662     GstQuery * query)
663 {
664   gboolean res = FALSE;
665   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
666
667   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
668
669   switch (GST_QUERY_TYPE (query)) {
670     case GST_QUERY_POSITION:{
671       GstFormat fmt;
672
673       gst_query_parse_position (query, &fmt, NULL);
674       if (fmt == GST_FORMAT_TIME
675           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
676         gst_query_set_position (query, GST_FORMAT_TIME,
677             qtdemux->segment.position);
678         res = TRUE;
679       }
680     }
681       break;
682     case GST_QUERY_DURATION:{
683       GstFormat fmt;
684
685       gst_query_parse_duration (query, &fmt, NULL);
686       if (fmt == GST_FORMAT_TIME) {
687         /* First try to query upstream */
688         res = gst_pad_query_default (pad, parent, query);
689         if (!res) {
690           GstClockTime duration;
691           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
692             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
693             res = TRUE;
694           }
695         }
696       }
697       break;
698     }
699     case GST_QUERY_CONVERT:{
700       GstFormat src_fmt, dest_fmt;
701       gint64 src_value, dest_value = 0;
702
703       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
704
705       res = gst_qtdemux_src_convert (qtdemux, pad,
706           src_fmt, src_value, dest_fmt, &dest_value);
707       if (res)
708         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
709
710       break;
711     }
712     case GST_QUERY_FORMATS:
713       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
714       res = TRUE;
715       break;
716     case GST_QUERY_SEEKING:{
717       GstFormat fmt;
718       gboolean seekable;
719
720       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
721
722       if (fmt == GST_FORMAT_BYTES) {
723         /* We always refuse BYTES seeks from downstream */
724         break;
725       }
726
727       /* try upstream first */
728       res = gst_pad_query_default (pad, parent, query);
729
730       if (!res) {
731         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
732         if (fmt == GST_FORMAT_TIME) {
733           GstClockTime duration;
734
735           gst_qtdemux_get_duration (qtdemux, &duration);
736           seekable = TRUE;
737           if (!qtdemux->pullbased) {
738             GstQuery *q;
739
740             /* we might be able with help from upstream */
741             seekable = FALSE;
742             q = gst_query_new_seeking (GST_FORMAT_BYTES);
743             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
744               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
745               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
746             }
747             gst_query_unref (q);
748           }
749           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
750           res = TRUE;
751         }
752       }
753       break;
754     }
755     case GST_QUERY_SEGMENT:
756     {
757       GstFormat format;
758       gint64 start, stop;
759
760       format = qtdemux->segment.format;
761
762       start =
763           gst_segment_to_stream_time (&qtdemux->segment, format,
764           qtdemux->segment.start);
765       if ((stop = qtdemux->segment.stop) == -1)
766         stop = qtdemux->segment.duration;
767       else
768         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
769
770       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
771       res = TRUE;
772       break;
773     }
774     default:
775       res = gst_pad_query_default (pad, parent, query);
776       break;
777   }
778
779   return res;
780 }
781
782 static void
783 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
784 {
785   if (G_LIKELY (stream->pad)) {
786     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
787         GST_DEBUG_PAD_NAME (stream->pad));
788
789     if (!gst_tag_list_is_empty (stream->stream_tags)) {
790       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
791           stream->stream_tags);
792       gst_pad_push_event (stream->pad,
793           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
794     }
795
796     if (G_UNLIKELY (stream->send_global_tags)) {
797       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
798           qtdemux->tag_list);
799       gst_pad_push_event (stream->pad,
800           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
801       stream->send_global_tags = FALSE;
802     }
803   }
804 }
805
806 /* push event on all source pads; takes ownership of the event */
807 static void
808 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
809 {
810   gboolean has_valid_stream = FALSE;
811   GstEventType etype = GST_EVENT_TYPE (event);
812   guint i;
813
814   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
815       GST_EVENT_TYPE_NAME (event));
816
817   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
818     GstPad *pad;
819     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
820     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
821
822     if ((pad = stream->pad)) {
823       has_valid_stream = TRUE;
824
825       if (etype == GST_EVENT_EOS) {
826         /* let's not send twice */
827         if (stream->sent_eos)
828           continue;
829         stream->sent_eos = TRUE;
830       }
831
832       gst_pad_push_event (pad, gst_event_ref (event));
833     }
834   }
835
836   gst_event_unref (event);
837
838   /* if it is EOS and there are no pads, post an error */
839   if (!has_valid_stream && etype == GST_EVENT_EOS) {
840     gst_qtdemux_post_no_playable_stream_error (qtdemux);
841   }
842 }
843
844 typedef struct
845 {
846   guint64 media_time;
847 } FindData;
848
849 static gint
850 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
851 {
852   if ((gint64) s1->timestamp > *media_time)
853     return 1;
854   if ((gint64) s1->timestamp == *media_time)
855     return 0;
856
857   return -1;
858 }
859
860 /* find the index of the sample that includes the data for @media_time using a
861  * binary search.  Only to be called in optimized cases of linear search below.
862  *
863  * Returns the index of the sample with the corresponding *DTS*.
864  */
865 static guint32
866 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
867     guint64 media_time)
868 {
869   QtDemuxSample *result;
870   guint32 index;
871
872   /* convert media_time to mov format */
873   media_time =
874       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
875
876   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
877       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
878       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
879
880   if (G_LIKELY (result))
881     index = result - str->samples;
882   else
883     index = 0;
884
885   return index;
886 }
887
888
889
890 /* find the index of the sample that includes the data for @media_offset using a
891  * linear search
892  *
893  * Returns the index of the sample.
894  */
895 static guint32
896 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
897     QtDemuxStream * str, gint64 media_offset)
898 {
899   QtDemuxSample *result = str->samples;
900   guint32 index = 0;
901
902   if (result == NULL || str->n_samples == 0)
903     return -1;
904
905   if (media_offset == result->offset)
906     return index;
907
908   result++;
909   while (index < str->n_samples - 1) {
910     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
911       goto parse_failed;
912
913     if (media_offset < result->offset)
914       break;
915
916     index++;
917     result++;
918   }
919   return index;
920
921   /* ERRORS */
922 parse_failed:
923   {
924     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
925     return -1;
926   }
927 }
928
929 /* find the index of the sample that includes the data for @media_time using a
930  * linear search, and keeping in mind that not all samples may have been parsed
931  * yet.  If possible, it will delegate to binary search.
932  *
933  * Returns the index of the sample.
934  */
935 static guint32
936 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
937     GstClockTime media_time)
938 {
939   guint32 index = 0;
940   guint64 mov_time;
941   QtDemuxSample *sample;
942
943   /* convert media_time to mov format */
944   mov_time =
945       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
946
947   sample = str->samples;
948   if (mov_time == sample->timestamp + sample->pts_offset)
949     return index;
950
951   /* use faster search if requested time in already parsed range */
952   sample = str->samples + str->stbl_index;
953   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
954     index = gst_qtdemux_find_index (qtdemux, str, media_time);
955     sample = str->samples + index;
956   } else {
957     while (index < str->n_samples - 1) {
958       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
959         goto parse_failed;
960
961       sample = str->samples + index + 1;
962       if (mov_time < sample->timestamp) {
963         sample = str->samples + index;
964         break;
965       }
966
967       index++;
968     }
969   }
970
971   /* sample->timestamp is now <= media_time, need to find the corresponding
972    * PTS now by looking backwards */
973   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
974     index--;
975     sample = str->samples + index;
976   }
977
978   return index;
979
980   /* ERRORS */
981 parse_failed:
982   {
983     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
984     return -1;
985   }
986 }
987
988 /* find the index of the keyframe needed to decode the sample at @index
989  * of stream @str, or of a subsequent keyframe (depending on @next)
990  *
991  * Returns the index of the keyframe.
992  */
993 static guint32
994 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
995     guint32 index, gboolean next)
996 {
997   guint32 new_index = index;
998
999   if (index >= str->n_samples) {
1000     new_index = str->n_samples;
1001     goto beach;
1002   }
1003
1004   /* all keyframes, return index */
1005   if (str->all_keyframe) {
1006     new_index = index;
1007     goto beach;
1008   }
1009
1010   /* else search until we have a keyframe */
1011   while (new_index < str->n_samples) {
1012     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1013       goto parse_failed;
1014
1015     if (str->samples[new_index].keyframe)
1016       break;
1017
1018     if (new_index == 0)
1019       break;
1020
1021     if (next)
1022       new_index++;
1023     else
1024       new_index--;
1025   }
1026
1027   if (new_index == str->n_samples) {
1028     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1029     new_index = -1;
1030   }
1031
1032 beach:
1033   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1034       "gave %u", next ? "after" : "before", index, new_index);
1035
1036   return new_index;
1037
1038   /* ERRORS */
1039 parse_failed:
1040   {
1041     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1042     return -1;
1043   }
1044 }
1045
1046 /* find the segment for @time_position for @stream
1047  *
1048  * Returns the index of the segment containing @time_position.
1049  * Returns the last segment and sets the @eos variable to TRUE
1050  * if the time is beyond the end. @eos may be NULL
1051  */
1052 static guint32
1053 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1054     GstClockTime time_position)
1055 {
1056   gint i;
1057   guint32 seg_idx;
1058
1059   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1060       GST_TIME_ARGS (time_position));
1061
1062   seg_idx = -1;
1063   for (i = 0; i < stream->n_segments; i++) {
1064     QtDemuxSegment *segment = &stream->segments[i];
1065
1066     GST_LOG_OBJECT (stream->pad,
1067         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1068         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1069
1070     /* For the last segment we include stop_time in the last segment */
1071     if (i < stream->n_segments - 1) {
1072       if (segment->time <= time_position && time_position < segment->stop_time) {
1073         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1074         seg_idx = i;
1075         break;
1076       }
1077     } else {
1078       /* Last segment always matches */
1079       seg_idx = i;
1080       break;
1081     }
1082   }
1083   return seg_idx;
1084 }
1085
1086 /* move the stream @str to the sample position @index.
1087  *
1088  * Updates @str->sample_index and marks discontinuity if needed.
1089  */
1090 static void
1091 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1092     guint32 index)
1093 {
1094   /* no change needed */
1095   if (index == str->sample_index)
1096     return;
1097
1098   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1099       str->n_samples);
1100
1101   /* position changed, we have a discont */
1102   str->sample_index = index;
1103   str->offset_in_sample = 0;
1104   /* Each time we move in the stream we store the position where we are
1105    * starting from */
1106   str->from_sample = index;
1107   str->discont = TRUE;
1108 }
1109
1110 static void
1111 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1112     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1113 {
1114   guint64 min_offset;
1115   gint64 min_byte_offset = -1;
1116   guint i;
1117
1118   min_offset = desired_time;
1119
1120   /* for each stream, find the index of the sample in the segment
1121    * and move back to the previous keyframe. */
1122   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1123     QtDemuxStream *str;
1124     guint32 index, kindex;
1125     guint32 seg_idx;
1126     GstClockTime media_start;
1127     GstClockTime media_time;
1128     GstClockTime seg_time;
1129     QtDemuxSegment *seg;
1130     gboolean empty_segment = FALSE;
1131
1132     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1133
1134     if (CUR_STREAM (str)->sparse && !use_sparse)
1135       continue;
1136
1137     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1138     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1139
1140     /* get segment and time in the segment */
1141     seg = &str->segments[seg_idx];
1142     seg_time = (desired_time - seg->time) * seg->rate;
1143
1144     while (QTSEGMENT_IS_EMPTY (seg)) {
1145       seg_time = 0;
1146       empty_segment = TRUE;
1147       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1148           seg_idx);
1149       seg_idx++;
1150       if (seg_idx == str->n_segments)
1151         break;
1152       seg = &str->segments[seg_idx];
1153     }
1154
1155     if (seg_idx == str->n_segments) {
1156       /* FIXME track shouldn't have the last segment as empty, but if it
1157        * happens we better handle it */
1158       continue;
1159     }
1160
1161     /* get the media time in the segment */
1162     media_start = seg->media_start + seg_time;
1163
1164     /* get the index of the sample with media time */
1165     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1166     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1167         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1168         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1169         empty_segment);
1170
1171     /* shift to next frame if we are looking for next keyframe */
1172     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1173         && index < str->stbl_index)
1174       index++;
1175
1176     if (!empty_segment) {
1177       /* find previous keyframe */
1178       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1179
1180       /* we will settle for one before if none found after */
1181       if (next && kindex == -1)
1182         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1183
1184       /* Update the requested time whenever a keyframe was found, to make it
1185        * accurate and avoid having the first buffer fall outside of the segment
1186        */
1187       if (kindex != -1) {
1188         index = kindex;
1189
1190         /* get timestamp of keyframe */
1191         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1192         GST_DEBUG_OBJECT (qtdemux,
1193             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1194             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1195             str->samples[kindex].offset);
1196
1197         /* keyframes in the segment get a chance to change the
1198          * desired_offset. keyframes out of the segment are
1199          * ignored. */
1200         if (media_time >= seg->media_start) {
1201           GstClockTime seg_time;
1202
1203           /* this keyframe is inside the segment, convert back to
1204            * segment time */
1205           seg_time = (media_time - seg->media_start) + seg->time;
1206           if ((!next && (seg_time < min_offset)) ||
1207               (next && (seg_time > min_offset)))
1208             min_offset = seg_time;
1209         }
1210       }
1211     }
1212
1213     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1214       min_byte_offset = str->samples[index].offset;
1215   }
1216
1217   if (key_time)
1218     *key_time = min_offset;
1219   if (key_offset)
1220     *key_offset = min_byte_offset;
1221 }
1222
1223 static gboolean
1224 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1225     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1226 {
1227   gboolean res;
1228
1229   g_return_val_if_fail (format != NULL, FALSE);
1230   g_return_val_if_fail (cur != NULL, FALSE);
1231   g_return_val_if_fail (stop != NULL, FALSE);
1232
1233   if (*format == GST_FORMAT_TIME)
1234     return TRUE;
1235
1236   res = TRUE;
1237   if (cur_type != GST_SEEK_TYPE_NONE)
1238     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1239   if (res && stop_type != GST_SEEK_TYPE_NONE)
1240     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1241
1242   if (res)
1243     *format = GST_FORMAT_TIME;
1244
1245   return res;
1246 }
1247
1248 /* perform seek in push based mode:
1249    find BYTE position to move to based on time and delegate to upstream
1250 */
1251 static gboolean
1252 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1253 {
1254   gdouble rate;
1255   GstFormat format;
1256   GstSeekFlags flags;
1257   GstSeekType cur_type, stop_type;
1258   gint64 cur, stop, key_cur;
1259   gboolean res;
1260   gint64 byte_cur;
1261   gint64 original_stop;
1262   guint32 seqnum;
1263
1264   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1265
1266   gst_event_parse_seek (event, &rate, &format, &flags,
1267       &cur_type, &cur, &stop_type, &stop);
1268   seqnum = gst_event_get_seqnum (event);
1269
1270   /* Directly send the instant-rate-change event here before taking the
1271    * stream-lock so that it can be applied as soon as possible */
1272   if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
1273     GstEvent *ev;
1274
1275     /* instant rate change only supported if direction does not change. All
1276      * other requirements are already checked before creating the seek event
1277      * but let's double-check here to be sure */
1278     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1279         (qtdemux->segment.rate < 0 && rate > 0) ||
1280         cur_type != GST_SEEK_TYPE_NONE ||
1281         stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) {
1282       GST_ERROR_OBJECT (qtdemux,
1283           "Instant rate change seeks only supported in the "
1284           "same direction, without flushing and position change");
1285       return FALSE;
1286     }
1287
1288     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1289         (GstSegmentFlags) flags);
1290     gst_event_set_seqnum (ev, seqnum);
1291     gst_qtdemux_push_event (qtdemux, ev);
1292     return TRUE;
1293   }
1294
1295   /* only forward streaming and seeking is possible */
1296   if (rate <= 0)
1297     goto unsupported_seek;
1298
1299   /* convert to TIME if needed and possible */
1300   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1301           stop_type, &stop))
1302     goto no_format;
1303
1304   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1305    * the original stop position to use when upstream pushes the new segment
1306    * for this seek */
1307   original_stop = stop;
1308   stop = -1;
1309
1310   /* find reasonable corresponding BYTE position,
1311    * also try to mind about keyframes, since we can not go back a bit for them
1312    * later on */
1313   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1314    * mostly just work, but let's not yet boldly go there  ... */
1315   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1316
1317   if (byte_cur == -1)
1318     goto abort_seek;
1319
1320   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1321       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1322       stop);
1323
1324   GST_OBJECT_LOCK (qtdemux);
1325   qtdemux->seek_offset = byte_cur;
1326   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1327     qtdemux->push_seek_start = cur;
1328   } else {
1329     qtdemux->push_seek_start = key_cur;
1330   }
1331
1332   if (stop_type == GST_SEEK_TYPE_NONE) {
1333     qtdemux->push_seek_stop = qtdemux->segment.stop;
1334   } else {
1335     qtdemux->push_seek_stop = original_stop;
1336   }
1337   GST_OBJECT_UNLOCK (qtdemux);
1338
1339   qtdemux->segment_seqnum = seqnum;
1340   /* BYTE seek event */
1341   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1342       stop_type, stop);
1343   gst_event_set_seqnum (event, seqnum);
1344   res = gst_pad_push_event (qtdemux->sinkpad, event);
1345
1346   return res;
1347
1348   /* ERRORS */
1349 abort_seek:
1350   {
1351     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1352         "seek aborted.");
1353     return FALSE;
1354   }
1355 unsupported_seek:
1356   {
1357     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1358     return FALSE;
1359   }
1360 no_format:
1361   {
1362     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1363     return FALSE;
1364   }
1365 }
1366
1367 /* perform the seek.
1368  *
1369  * We set all segment_indexes in the streams to unknown and
1370  * adjust the time_position to the desired position. this is enough
1371  * to trigger a segment switch in the streaming thread to start
1372  * streaming from the desired position.
1373  *
1374  * Keyframe seeking is a little more complicated when dealing with
1375  * segments. Ideally we want to move to the previous keyframe in
1376  * the segment but there might not be a keyframe in the segment. In
1377  * fact, none of the segments could contain a keyframe. We take a
1378  * practical approach: seek to the previous keyframe in the segment,
1379  * if there is none, seek to the beginning of the segment.
1380  *
1381  * Called with STREAM_LOCK
1382  */
1383 static gboolean
1384 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1385     guint32 seqnum, GstSeekFlags flags)
1386 {
1387   gint64 desired_offset;
1388   guint i;
1389
1390   desired_offset = segment->position;
1391
1392   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1393       GST_TIME_ARGS (desired_offset));
1394
1395   /* may not have enough fragmented info to do this adjustment,
1396    * and we can't scan (and probably should not) at this time with
1397    * possibly flushing upstream */
1398   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1399     gint64 min_offset;
1400     gboolean next, before, after;
1401
1402     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1403     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1404     next = after && !before;
1405     if (segment->rate < 0)
1406       next = !next;
1407
1408     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1409         NULL);
1410     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1411         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1412     desired_offset = min_offset;
1413   }
1414
1415   /* and set all streams to the final position */
1416   GST_OBJECT_LOCK (qtdemux);
1417   gst_flow_combiner_reset (qtdemux->flowcombiner);
1418   GST_OBJECT_UNLOCK (qtdemux);
1419   qtdemux->segment_seqnum = seqnum;
1420   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1421     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1422
1423     stream->time_position = desired_offset;
1424     stream->accumulated_base = 0;
1425     stream->sample_index = -1;
1426     stream->offset_in_sample = 0;
1427     stream->segment_index = -1;
1428     stream->sent_eos = FALSE;
1429     stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
1430
1431     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1432       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1433   }
1434   segment->position = desired_offset;
1435   if (segment->rate >= 0) {
1436     segment->start = desired_offset;
1437     /* We need to update time as we update start in that direction */
1438     segment->time = desired_offset;
1439
1440     /* we stop at the end */
1441     if (segment->stop == -1)
1442       segment->stop = segment->duration;
1443   } else {
1444     segment->stop = desired_offset;
1445   }
1446
1447   if (qtdemux->fragmented)
1448     qtdemux->fragmented_seek_pending = TRUE;
1449
1450   return TRUE;
1451 }
1452
1453 /* do a seek in pull based mode */
1454 static gboolean
1455 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1456 {
1457   gdouble rate = 1.0;
1458   GstFormat format;
1459   GstSeekFlags flags;
1460   GstSeekType cur_type, stop_type;
1461   gint64 cur, stop;
1462   gboolean flush, instant_rate_change;
1463   gboolean update;
1464   GstSegment seeksegment;
1465   guint32 seqnum = GST_SEQNUM_INVALID;
1466   GstEvent *flush_event;
1467   gboolean ret;
1468
1469   GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1470
1471   gst_event_parse_seek (event, &rate, &format, &flags,
1472       &cur_type, &cur, &stop_type, &stop);
1473   seqnum = gst_event_get_seqnum (event);
1474
1475   /* we have to have a format as the segment format. Try to convert
1476    * if not. */
1477   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1478           stop_type, &stop))
1479     goto no_format;
1480
1481   GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1482
1483   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
1484   instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1485
1486   /* Directly send the instant-rate-change event here before taking the
1487    * stream-lock so that it can be applied as soon as possible */
1488   if (instant_rate_change) {
1489     GstEvent *ev;
1490
1491     /* instant rate change only supported if direction does not change. All
1492      * other requirements are already checked before creating the seek event
1493      * but let's double-check here to be sure */
1494     if ((qtdemux->segment.rate > 0 && rate < 0) ||
1495         (qtdemux->segment.rate < 0 && rate > 0) ||
1496         cur_type != GST_SEEK_TYPE_NONE ||
1497         stop_type != GST_SEEK_TYPE_NONE || flush) {
1498       GST_ERROR_OBJECT (qtdemux,
1499           "Instant rate change seeks only supported in the "
1500           "same direction, without flushing and position change");
1501       return FALSE;
1502     }
1503
1504     ev = gst_event_new_instant_rate_change (rate / qtdemux->segment.rate,
1505         (GstSegmentFlags) flags);
1506     gst_event_set_seqnum (ev, seqnum);
1507     gst_qtdemux_push_event (qtdemux, ev);
1508     return TRUE;
1509   }
1510
1511   /* stop streaming, either by flushing or by pausing the task */
1512   if (flush) {
1513     flush_event = gst_event_new_flush_start ();
1514     if (seqnum != GST_SEQNUM_INVALID)
1515       gst_event_set_seqnum (flush_event, seqnum);
1516     /* unlock upstream pull_range */
1517     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1518     /* make sure out loop function exits */
1519     gst_qtdemux_push_event (qtdemux, flush_event);
1520   } else {
1521     /* non flushing seek, pause the task */
1522     gst_pad_pause_task (qtdemux->sinkpad);
1523   }
1524
1525   /* wait for streaming to finish */
1526   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1527
1528   /* copy segment, we need this because we still need the old
1529    * segment when we close the current segment. */
1530   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1531
1532   /* configure the segment with the seek variables */
1533   GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1534   if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1535           cur_type, cur, stop_type, stop, &update)) {
1536     ret = FALSE;
1537     GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1538   } else {
1539     /* now do the seek */
1540     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1541   }
1542
1543   /* prepare for streaming again */
1544   if (flush) {
1545     flush_event = gst_event_new_flush_stop (TRUE);
1546     if (seqnum != GST_SEQNUM_INVALID)
1547       gst_event_set_seqnum (flush_event, seqnum);
1548
1549     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1550     gst_qtdemux_push_event (qtdemux, flush_event);
1551   }
1552
1553   /* commit the new segment */
1554   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1555
1556   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1557     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1558         qtdemux->segment.format, qtdemux->segment.position);
1559     if (seqnum != GST_SEQNUM_INVALID)
1560       gst_message_set_seqnum (msg, seqnum);
1561     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1562   }
1563
1564   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1565   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1566       qtdemux->sinkpad, NULL);
1567
1568   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1569
1570   return ret;
1571
1572   /* ERRORS */
1573 no_format:
1574   {
1575     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1576     return FALSE;
1577   }
1578 }
1579
1580 static gboolean
1581 qtdemux_ensure_index (GstQTDemux * qtdemux)
1582 {
1583   guint i;
1584
1585   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1586
1587   /* Build complete index */
1588   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1589     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1590
1591     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1592       GST_LOG_OBJECT (qtdemux,
1593           "Building complete index of track-id %u for seeking failed!",
1594           stream->track_id);
1595       return FALSE;
1596     }
1597   }
1598
1599   return TRUE;
1600 }
1601
1602 static gboolean
1603 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1604     GstEvent * event)
1605 {
1606   gboolean res = TRUE;
1607   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1608
1609   switch (GST_EVENT_TYPE (event)) {
1610     case GST_EVENT_RECONFIGURE:
1611       GST_OBJECT_LOCK (qtdemux);
1612       gst_flow_combiner_reset (qtdemux->flowcombiner);
1613       GST_OBJECT_UNLOCK (qtdemux);
1614       res = gst_pad_event_default (pad, parent, event);
1615       break;
1616     case GST_EVENT_SEEK:
1617     {
1618       GstSeekFlags flags = 0;
1619       GstFormat seek_format;
1620       gboolean instant_rate_change;
1621
1622 #ifndef GST_DISABLE_GST_DEBUG
1623       GstClockTime ts = gst_util_get_timestamp ();
1624 #endif
1625       guint32 seqnum = gst_event_get_seqnum (event);
1626
1627       qtdemux->received_seek = TRUE;
1628
1629       gst_event_parse_seek (event, NULL, &seek_format, &flags, NULL, NULL, NULL,
1630           NULL);
1631       instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE);
1632
1633       if (seqnum == qtdemux->segment_seqnum) {
1634         GST_LOG_OBJECT (pad,
1635             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1636         gst_event_unref (event);
1637         return TRUE;
1638       }
1639
1640       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1641         /* seek should be handled by upstream, we might need to re-download fragments */
1642         GST_DEBUG_OBJECT (qtdemux,
1643             "let upstream handle seek for fragmented playback");
1644         goto upstream;
1645       }
1646
1647       if (seek_format == GST_FORMAT_BYTES) {
1648         GST_DEBUG_OBJECT (pad, "Rejecting seek request in bytes format");
1649         gst_event_unref (event);
1650         return FALSE;
1651       }
1652
1653       gst_event_parse_seek_trickmode_interval (event,
1654           &qtdemux->trickmode_interval);
1655
1656       /* Build complete index for seeking;
1657        * if not a fragmented file at least and we're really doing a seek,
1658        * not just an instant-rate-change */
1659       if (!qtdemux->fragmented && !instant_rate_change) {
1660         if (!qtdemux_ensure_index (qtdemux))
1661           goto index_failed;
1662       }
1663 #ifndef GST_DISABLE_GST_DEBUG
1664       ts = gst_util_get_timestamp () - ts;
1665       GST_INFO_OBJECT (qtdemux,
1666           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1667 #endif
1668       if (qtdemux->pullbased) {
1669         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1670       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1671         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1672         res = TRUE;
1673       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1674           && QTDEMUX_N_STREAMS (qtdemux)
1675           && !qtdemux->fragmented) {
1676         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1677       } else {
1678         GST_DEBUG_OBJECT (qtdemux,
1679             "ignoring seek in push mode in current state");
1680         res = FALSE;
1681       }
1682       gst_event_unref (event);
1683     }
1684       break;
1685     default:
1686     upstream:
1687       res = gst_pad_event_default (pad, parent, event);
1688       break;
1689   }
1690
1691 done:
1692   return res;
1693
1694   /* ERRORS */
1695 index_failed:
1696   {
1697     GST_ERROR_OBJECT (qtdemux, "Index failed");
1698     gst_event_unref (event);
1699     res = FALSE;
1700     goto done;
1701   }
1702 }
1703
1704 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1705  *
1706  * If @fw is false, the coding order is explored backwards.
1707  *
1708  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1709  * sample is found for that track.
1710  *
1711  * The stream and sample index of the sample with the minimum offset in the direction explored
1712  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1713  *
1714  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1715  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1716  * @_stream and @_index. */
1717 static void
1718 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1719     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1720 {
1721   gint i, index;
1722   gint64 time, min_time;
1723   QtDemuxStream *stream;
1724   gint iter;
1725
1726   min_time = -1;
1727   stream = NULL;
1728   index = -1;
1729
1730   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1731     QtDemuxStream *str;
1732     gint inc;
1733     gboolean set_sample;
1734
1735     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1736     set_sample = !set;
1737
1738     if (fw) {
1739       i = 0;
1740       inc = 1;
1741     } else {
1742       i = str->n_samples - 1;
1743       inc = -1;
1744     }
1745
1746     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1747       if (str->samples[i].size == 0)
1748         continue;
1749
1750       if (fw && (str->samples[i].offset < byte_pos))
1751         continue;
1752
1753       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1754         continue;
1755
1756       /* move stream to first available sample */
1757       if (set) {
1758         gst_qtdemux_move_stream (qtdemux, str, i);
1759         set_sample = TRUE;
1760       }
1761
1762       /* avoid index from sparse streams since they might be far away */
1763       if (!CUR_STREAM (str)->sparse) {
1764         /* determine min/max time */
1765         time = QTSAMPLE_PTS (str, &str->samples[i]);
1766         if (min_time == -1 || (!fw && time > min_time) ||
1767             (fw && time < min_time)) {
1768           min_time = time;
1769         }
1770
1771         /* determine stream with leading sample, to get its position */
1772         if (!stream ||
1773             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1774             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1775           stream = str;
1776           index = i;
1777         }
1778       }
1779       break;
1780     }
1781
1782     /* no sample for this stream, mark eos */
1783     if (!set_sample)
1784       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1785   }
1786
1787   if (_time)
1788     *_time = min_time;
1789   if (_stream)
1790     *_stream = stream;
1791   if (_index)
1792     *_index = index;
1793 }
1794
1795 /* Copied from mpegtsbase code */
1796 /* FIXME: replace this function when we add new util function for stream-id creation */
1797 static gchar *
1798 _get_upstream_id (GstQTDemux * demux)
1799 {
1800   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1801
1802   if (!upstream_id) {
1803     /* Try to create one from the upstream URI, else use a randome number */
1804     GstQuery *query;
1805     gchar *uri = NULL;
1806
1807     /* Try to generate one from the URI query and
1808      * if it fails take a random number instead */
1809     query = gst_query_new_uri ();
1810     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1811       gst_query_parse_uri (query, &uri);
1812     }
1813
1814     if (uri) {
1815       GChecksum *cs;
1816
1817       /* And then generate an SHA256 sum of the URI */
1818       cs = g_checksum_new (G_CHECKSUM_SHA256);
1819       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1820       g_free (uri);
1821       upstream_id = g_strdup (g_checksum_get_string (cs));
1822       g_checksum_free (cs);
1823     } else {
1824       /* Just get some random number if the URI query fails */
1825       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1826           "implementing a deterministic way of creating a stream-id");
1827       upstream_id =
1828           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1829           g_random_int (), g_random_int ());
1830     }
1831
1832     gst_query_unref (query);
1833   }
1834   return upstream_id;
1835 }
1836
1837 static QtDemuxStream *
1838 _create_stream (GstQTDemux * demux, guint32 track_id)
1839 {
1840   QtDemuxStream *stream;
1841   gchar *upstream_id;
1842
1843   stream = g_new0 (QtDemuxStream, 1);
1844   stream->demux = demux;
1845   stream->track_id = track_id;
1846   upstream_id = _get_upstream_id (demux);
1847   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1848   g_free (upstream_id);
1849   /* new streams always need a discont */
1850   stream->discont = TRUE;
1851   /* we enable clipping for raw audio/video streams */
1852   stream->need_clip = FALSE;
1853   stream->process_func = NULL;
1854   stream->segment_index = -1;
1855   stream->time_position = 0;
1856   stream->sample_index = -1;
1857   stream->offset_in_sample = 0;
1858   stream->new_stream = TRUE;
1859   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1860   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1861   stream->protected = FALSE;
1862   stream->protection_scheme_type = 0;
1863   stream->protection_scheme_version = 0;
1864   stream->protection_scheme_info = NULL;
1865   stream->n_samples_moof = 0;
1866   stream->duration_moof = 0;
1867   stream->duration_last_moof = 0;
1868   stream->alignment = 1;
1869   stream->stream_tags = gst_tag_list_new_empty ();
1870   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1871   g_queue_init (&stream->protection_scheme_event_queue);
1872   stream->ref_count = 1;
1873   /* consistent default for push based mode */
1874   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1875   return stream;
1876 }
1877
1878 static gboolean
1879 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1880 {
1881   GstStructure *structure;
1882   const gchar *variant;
1883   const GstCaps *mediacaps = NULL;
1884
1885   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1886
1887   structure = gst_caps_get_structure (caps, 0);
1888   variant = gst_structure_get_string (structure, "variant");
1889
1890   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1891     QtDemuxStream *stream;
1892     const GValue *value;
1893
1894     demux->fragmented = TRUE;
1895     demux->mss_mode = TRUE;
1896
1897     if (QTDEMUX_N_STREAMS (demux) > 1) {
1898       /* can't do this, we can only renegotiate for another mss format */
1899       return FALSE;
1900     }
1901
1902     value = gst_structure_get_value (structure, "media-caps");
1903     /* create stream */
1904     if (value) {
1905       const GValue *timescale_v;
1906
1907       /* TODO update when stream changes during playback */
1908
1909       if (QTDEMUX_N_STREAMS (demux) == 0) {
1910         stream = _create_stream (demux, 1);
1911         g_ptr_array_add (demux->active_streams, stream);
1912         /* mss has no stsd/stsd entry, use id 0 as default */
1913         stream->stsd_entries_length = 1;
1914         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1915         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1916       } else {
1917         stream = QTDEMUX_NTH_STREAM (demux, 0);
1918       }
1919
1920       timescale_v = gst_structure_get_value (structure, "timescale");
1921       if (timescale_v) {
1922         stream->timescale = g_value_get_uint64 (timescale_v);
1923       } else {
1924         /* default mss timescale */
1925         stream->timescale = 10000000;
1926       }
1927       demux->timescale = stream->timescale;
1928
1929       mediacaps = gst_value_get_caps (value);
1930       if (!CUR_STREAM (stream)->caps
1931           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1932         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1933             mediacaps);
1934         stream->new_caps = TRUE;
1935       }
1936       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1937       structure = gst_caps_get_structure (mediacaps, 0);
1938       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
1939         stream->subtype = FOURCC_vide;
1940
1941         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
1942         gst_structure_get_int (structure, "height",
1943             &CUR_STREAM (stream)->height);
1944         gst_structure_get_fraction (structure, "framerate",
1945             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
1946       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
1947         gint rate = 0;
1948         stream->subtype = FOURCC_soun;
1949         gst_structure_get_int (structure, "channels",
1950             &CUR_STREAM (stream)->n_channels);
1951         gst_structure_get_int (structure, "rate", &rate);
1952         CUR_STREAM (stream)->rate = rate;
1953       } else if (gst_structure_has_name (structure, "application/x-cenc")) {
1954         if (gst_structure_has_field (structure, "original-media-type")) {
1955           const gchar *media_type =
1956               gst_structure_get_string (structure, "original-media-type");
1957           if (g_str_has_prefix (media_type, "video")) {
1958             stream->subtype = FOURCC_vide;
1959           } else if (g_str_has_prefix (media_type, "audio")) {
1960             stream->subtype = FOURCC_soun;
1961           }
1962         }
1963       }
1964     }
1965     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
1966   } else {
1967     demux->mss_mode = FALSE;
1968   }
1969
1970   return TRUE;
1971 }
1972
1973 static void
1974 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
1975 {
1976   gint i;
1977
1978   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
1979   gst_pad_stop_task (qtdemux->sinkpad);
1980
1981   if (hard || qtdemux->upstream_format_is_time) {
1982     qtdemux->state = QTDEMUX_STATE_INITIAL;
1983     qtdemux->neededbytes = 16;
1984     qtdemux->todrop = 0;
1985     qtdemux->pullbased = FALSE;
1986     g_clear_pointer (&qtdemux->redirect_location, g_free);
1987     qtdemux->first_mdat = -1;
1988     qtdemux->header_size = 0;
1989     qtdemux->mdatoffset = -1;
1990     qtdemux->restoredata_offset = -1;
1991     if (qtdemux->mdatbuffer)
1992       gst_buffer_unref (qtdemux->mdatbuffer);
1993     if (qtdemux->restoredata_buffer)
1994       gst_buffer_unref (qtdemux->restoredata_buffer);
1995     qtdemux->mdatbuffer = NULL;
1996     qtdemux->restoredata_buffer = NULL;
1997     qtdemux->mdatleft = 0;
1998     qtdemux->mdatsize = 0;
1999     if (qtdemux->comp_brands)
2000       gst_buffer_unref (qtdemux->comp_brands);
2001     qtdemux->comp_brands = NULL;
2002     qtdemux->last_moov_offset = -1;
2003     if (qtdemux->moov_node_compressed) {
2004       g_node_destroy (qtdemux->moov_node_compressed);
2005       if (qtdemux->moov_node)
2006         g_free (qtdemux->moov_node->data);
2007     }
2008     qtdemux->moov_node_compressed = NULL;
2009     if (qtdemux->moov_node)
2010       g_node_destroy (qtdemux->moov_node);
2011     qtdemux->moov_node = NULL;
2012     if (qtdemux->tag_list)
2013       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2014     qtdemux->tag_list = gst_tag_list_new_empty ();
2015     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2016 #if 0
2017     if (qtdemux->element_index)
2018       gst_object_unref (qtdemux->element_index);
2019     qtdemux->element_index = NULL;
2020 #endif
2021     qtdemux->major_brand = 0;
2022     qtdemux->upstream_format_is_time = FALSE;
2023     qtdemux->upstream_seekable = FALSE;
2024     qtdemux->upstream_size = 0;
2025
2026     qtdemux->fragment_start = -1;
2027     qtdemux->fragment_start_offset = -1;
2028     qtdemux->duration = 0;
2029     qtdemux->moof_offset = 0;
2030     qtdemux->chapters_track_id = 0;
2031     qtdemux->have_group_id = FALSE;
2032     qtdemux->group_id = G_MAXUINT;
2033
2034     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2035         NULL);
2036     g_queue_clear (&qtdemux->protection_event_queue);
2037
2038     qtdemux->received_seek = FALSE;
2039     qtdemux->first_moof_already_parsed = FALSE;
2040   }
2041   qtdemux->offset = 0;
2042   gst_adapter_clear (qtdemux->adapter);
2043   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2044   qtdemux->need_segment = TRUE;
2045
2046   if (hard) {
2047     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2048     qtdemux->trickmode_interval = 0;
2049     g_ptr_array_set_size (qtdemux->active_streams, 0);
2050     g_ptr_array_set_size (qtdemux->old_streams, 0);
2051     qtdemux->n_video_streams = 0;
2052     qtdemux->n_audio_streams = 0;
2053     qtdemux->n_sub_streams = 0;
2054     qtdemux->exposed = FALSE;
2055     qtdemux->fragmented = FALSE;
2056     qtdemux->mss_mode = FALSE;
2057     gst_caps_replace (&qtdemux->media_caps, NULL);
2058     qtdemux->timescale = 0;
2059     qtdemux->got_moov = FALSE;
2060     qtdemux->cenc_aux_info_offset = 0;
2061     qtdemux->cenc_aux_info_sizes = NULL;
2062     qtdemux->cenc_aux_sample_count = 0;
2063     if (qtdemux->protection_system_ids) {
2064       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2065       qtdemux->protection_system_ids = NULL;
2066     }
2067     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2068         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2069         GST_BIN_FLAG_STREAMS_AWARE);
2070
2071     if (qtdemux->preferred_protection_system_id) {
2072       g_free (qtdemux->preferred_protection_system_id);
2073       qtdemux->preferred_protection_system_id = NULL;
2074     }
2075   } else if (qtdemux->mss_mode) {
2076     gst_flow_combiner_reset (qtdemux->flowcombiner);
2077     g_ptr_array_foreach (qtdemux->active_streams,
2078         (GFunc) gst_qtdemux_stream_clear, NULL);
2079   } else {
2080     gst_flow_combiner_reset (qtdemux->flowcombiner);
2081     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2082       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2083       stream->sent_eos = FALSE;
2084       stream->time_position = 0;
2085       stream->accumulated_base = 0;
2086       stream->last_keyframe_dts = GST_CLOCK_TIME_NONE;
2087     }
2088   }
2089 }
2090
2091
2092 /* Maps the @segment to the qt edts internal segments and pushes
2093  * the corresponding segment event.
2094  *
2095  * If it ends up being at a empty segment, a gap will be pushed and the next
2096  * edts segment will be activated in sequence.
2097  *
2098  * To be used in push-mode only */
2099 static void
2100 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2101 {
2102   gint i, iter;
2103
2104   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2105     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2106
2107     stream->time_position = segment->start;
2108
2109     /* in push mode we should be guaranteed that we will have empty segments
2110      * at the beginning and then one segment after, other scenarios are not
2111      * supported and are discarded when parsing the edts */
2112     for (i = 0; i < stream->n_segments; i++) {
2113       if (stream->segments[i].stop_time > segment->start) {
2114         /* push the empty segment and move to the next one */
2115         gst_qtdemux_activate_segment (qtdemux, stream, i,
2116             stream->time_position);
2117         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2118           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2119               stream->time_position);
2120
2121           /* accumulate previous segments */
2122           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2123             stream->accumulated_base +=
2124                 (stream->segment.stop -
2125                 stream->segment.start) / ABS (stream->segment.rate);
2126           continue;
2127         }
2128
2129         g_assert (i == stream->n_segments - 1);
2130       }
2131     }
2132   }
2133 }
2134
2135 static void
2136 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2137     GPtrArray * src)
2138 {
2139   guint i;
2140   guint len;
2141
2142   len = src->len;
2143
2144   if (len == 0)
2145     return;
2146
2147   for (i = 0; i < len; i++) {
2148     QtDemuxStream *stream = g_ptr_array_index (src, i);
2149
2150 #ifndef GST_DISABLE_GST_DEBUG
2151     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2152         stream, GST_STR_NULL (stream->stream_id), dest);
2153 #endif
2154     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2155   }
2156
2157   g_ptr_array_set_size (src, 0);
2158 }
2159
2160 static gboolean
2161 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2162     GstEvent * event)
2163 {
2164   GstQTDemux *demux = GST_QTDEMUX (parent);
2165   gboolean res = TRUE;
2166
2167   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2168
2169   switch (GST_EVENT_TYPE (event)) {
2170     case GST_EVENT_SEGMENT:
2171     {
2172       gint64 offset = 0;
2173       QtDemuxStream *stream;
2174       gint idx;
2175       GstSegment segment;
2176
2177       /* some debug output */
2178       gst_event_copy_segment (event, &segment);
2179       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2180           &segment);
2181
2182       if (segment.format == GST_FORMAT_TIME) {
2183         demux->upstream_format_is_time = TRUE;
2184         demux->segment_seqnum = gst_event_get_seqnum (event);
2185       } else {
2186         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2187             "not in time format");
2188
2189         /* chain will send initial newsegment after pads have been added */
2190         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2191           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2192           goto exit;
2193         }
2194       }
2195
2196       /* check if this matches a time seek we received previously
2197        * FIXME for backwards compatibility reasons we use the
2198        * seek_offset here to compare. In the future we might want to
2199        * change this to use the seqnum as it uniquely should identify
2200        * the segment that corresponds to the seek. */
2201       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2202           ", received segment offset %" G_GINT64_FORMAT,
2203           demux->seek_offset, segment.start);
2204       if (segment.format == GST_FORMAT_BYTES
2205           && demux->seek_offset == segment.start) {
2206         GST_OBJECT_LOCK (demux);
2207         offset = segment.start;
2208
2209         segment.format = GST_FORMAT_TIME;
2210         segment.start = demux->push_seek_start;
2211         segment.stop = demux->push_seek_stop;
2212         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2213             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2214             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2215         GST_OBJECT_UNLOCK (demux);
2216       }
2217
2218       /* we only expect a BYTE segment, e.g. following a seek */
2219       if (segment.format == GST_FORMAT_BYTES) {
2220         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2221           offset = segment.start;
2222
2223           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2224               NULL, (gint64 *) & segment.start);
2225           if ((gint64) segment.start < 0)
2226             segment.start = 0;
2227         }
2228         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2229           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2230               NULL, (gint64 *) & segment.stop);
2231           /* keyframe seeking should already arrange for start >= stop,
2232            * but make sure in other rare cases */
2233           segment.stop = MAX (segment.stop, segment.start);
2234         }
2235       } else if (segment.format == GST_FORMAT_TIME) {
2236         /* push all data on the adapter before starting this
2237          * new segment */
2238         gst_qtdemux_process_adapter (demux, TRUE);
2239       } else {
2240         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2241         goto exit;
2242       }
2243
2244       /* We shouldn't modify upstream driven TIME FORMAT segment */
2245       if (!demux->upstream_format_is_time) {
2246         /* accept upstream's notion of segment and distribute along */
2247         segment.format = GST_FORMAT_TIME;
2248         segment.position = segment.time = segment.start;
2249         segment.duration = demux->segment.duration;
2250         segment.base = gst_segment_to_running_time (&demux->segment,
2251             GST_FORMAT_TIME, demux->segment.position);
2252       }
2253
2254       gst_segment_copy_into (&segment, &demux->segment);
2255       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2256
2257       /* map segment to internal qt segments and push on each stream */
2258       if (QTDEMUX_N_STREAMS (demux)) {
2259         demux->need_segment = TRUE;
2260         gst_qtdemux_check_send_pending_segment (demux);
2261       }
2262
2263       /* clear leftover in current segment, if any */
2264       gst_adapter_clear (demux->adapter);
2265
2266       /* set up streaming thread */
2267       demux->offset = offset;
2268       if (demux->upstream_format_is_time) {
2269         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2270             "set values to restart reading from a new atom");
2271         demux->neededbytes = 16;
2272         demux->todrop = 0;
2273       } else {
2274         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2275             NULL);
2276         if (stream) {
2277           demux->todrop = stream->samples[idx].offset - offset;
2278           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2279         } else {
2280           /* set up for EOS */
2281           demux->neededbytes = -1;
2282           demux->todrop = 0;
2283         }
2284       }
2285     exit:
2286       gst_event_unref (event);
2287       res = TRUE;
2288       goto drop;
2289     }
2290     case GST_EVENT_FLUSH_START:
2291     {
2292       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2293         gst_event_unref (event);
2294         goto drop;
2295       }
2296       QTDEMUX_EXPOSE_LOCK (demux);
2297       res = gst_pad_event_default (demux->sinkpad, parent, event);
2298       QTDEMUX_EXPOSE_UNLOCK (demux);
2299       goto drop;
2300     }
2301     case GST_EVENT_FLUSH_STOP:
2302     {
2303       guint64 dur;
2304
2305       dur = demux->segment.duration;
2306       gst_qtdemux_reset (demux, FALSE);
2307       demux->segment.duration = dur;
2308
2309       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2310         gst_event_unref (event);
2311         goto drop;
2312       }
2313       break;
2314     }
2315     case GST_EVENT_EOS:
2316       /* If we are in push mode, and get an EOS before we've seen any streams,
2317        * then error out - we have nowhere to send the EOS */
2318       if (!demux->pullbased) {
2319         gint i;
2320         gboolean has_valid_stream = FALSE;
2321         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2322           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2323             has_valid_stream = TRUE;
2324             break;
2325           }
2326         }
2327         if (!has_valid_stream)
2328           gst_qtdemux_post_no_playable_stream_error (demux);
2329         else {
2330           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2331               (guint) gst_adapter_available (demux->adapter));
2332           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2333             res = FALSE;
2334           }
2335         }
2336       }
2337       break;
2338     case GST_EVENT_CAPS:{
2339       GstCaps *caps = NULL;
2340
2341       gst_event_parse_caps (event, &caps);
2342       gst_qtdemux_setcaps (demux, caps);
2343       res = TRUE;
2344       gst_event_unref (event);
2345       goto drop;
2346     }
2347     case GST_EVENT_PROTECTION:
2348     {
2349       const gchar *system_id = NULL;
2350
2351       gst_event_parse_protection (event, &system_id, NULL, NULL);
2352       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2353           system_id);
2354       gst_qtdemux_append_protection_system_id (demux, system_id);
2355       /* save the event for later, for source pads that have not been created */
2356       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2357       /* send it to all pads that already exist */
2358       gst_qtdemux_push_event (demux, event);
2359       res = TRUE;
2360       goto drop;
2361     }
2362     case GST_EVENT_STREAM_START:
2363     {
2364       res = TRUE;
2365       gst_event_unref (event);
2366
2367       /* Drain all the buffers */
2368       gst_qtdemux_process_adapter (demux, TRUE);
2369       gst_qtdemux_reset (demux, FALSE);
2370       /* We expect new moov box after new stream-start event */
2371       if (demux->exposed) {
2372         gst_qtdemux_stream_concat (demux,
2373             demux->old_streams, demux->active_streams);
2374       }
2375
2376       goto drop;
2377     }
2378     default:
2379       break;
2380   }
2381
2382   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2383
2384 drop:
2385   return res;
2386 }
2387
2388 static gboolean
2389 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2390     GstQuery * query)
2391 {
2392   GstQTDemux *demux = GST_QTDEMUX (parent);
2393   gboolean res = FALSE;
2394
2395   switch (GST_QUERY_TYPE (query)) {
2396     case GST_QUERY_BITRATE:
2397     {
2398       GstClockTime duration;
2399
2400       /* populate demux->upstream_size if not done yet */
2401       gst_qtdemux_check_seekability (demux);
2402
2403       if (demux->upstream_size != -1
2404           && gst_qtdemux_get_duration (demux, &duration)) {
2405         guint bitrate =
2406             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2407             duration);
2408
2409         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2410             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2411             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2412
2413         /* TODO: better results based on ranges/index tables */
2414         gst_query_set_bitrate (query, bitrate);
2415         res = TRUE;
2416       }
2417       break;
2418     }
2419     default:
2420       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2421       break;
2422   }
2423
2424   return res;
2425 }
2426
2427
2428 #if 0
2429 static void
2430 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2431 {
2432   GstQTDemux *demux = GST_QTDEMUX (element);
2433
2434   GST_OBJECT_LOCK (demux);
2435   if (demux->element_index)
2436     gst_object_unref (demux->element_index);
2437   if (index) {
2438     demux->element_index = gst_object_ref (index);
2439   } else {
2440     demux->element_index = NULL;
2441   }
2442   GST_OBJECT_UNLOCK (demux);
2443   /* object lock might be taken again */
2444   if (index)
2445     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2446   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2447       demux->element_index, demux->index_id);
2448 }
2449
2450 static GstIndex *
2451 gst_qtdemux_get_index (GstElement * element)
2452 {
2453   GstIndex *result = NULL;
2454   GstQTDemux *demux = GST_QTDEMUX (element);
2455
2456   GST_OBJECT_LOCK (demux);
2457   if (demux->element_index)
2458     result = gst_object_ref (demux->element_index);
2459   GST_OBJECT_UNLOCK (demux);
2460
2461   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2462
2463   return result;
2464 }
2465 #endif
2466
2467 static void
2468 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2469 {
2470   g_free ((gpointer) stream->stco.data);
2471   stream->stco.data = NULL;
2472   g_free ((gpointer) stream->stsz.data);
2473   stream->stsz.data = NULL;
2474   g_free ((gpointer) stream->stsc.data);
2475   stream->stsc.data = NULL;
2476   g_free ((gpointer) stream->stts.data);
2477   stream->stts.data = NULL;
2478   g_free ((gpointer) stream->stss.data);
2479   stream->stss.data = NULL;
2480   g_free ((gpointer) stream->stps.data);
2481   stream->stps.data = NULL;
2482   g_free ((gpointer) stream->ctts.data);
2483   stream->ctts.data = NULL;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2488 {
2489   g_free (stream->segments);
2490   stream->segments = NULL;
2491   stream->segment_index = -1;
2492   stream->accumulated_base = 0;
2493 }
2494
2495 static void
2496 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2497 {
2498   g_free (stream->samples);
2499   stream->samples = NULL;
2500   gst_qtdemux_stbl_free (stream);
2501
2502   /* fragments */
2503   g_free (stream->ra_entries);
2504   stream->ra_entries = NULL;
2505   stream->n_ra_entries = 0;
2506
2507   stream->sample_index = -1;
2508   stream->stbl_index = -1;
2509   stream->n_samples = 0;
2510   stream->time_position = 0;
2511
2512   stream->n_samples_moof = 0;
2513   stream->duration_moof = 0;
2514   stream->duration_last_moof = 0;
2515 }
2516
2517 static void
2518 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2519 {
2520   gint i;
2521   if (stream->allocator)
2522     gst_object_unref (stream->allocator);
2523   while (stream->buffers) {
2524     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2525     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2526   }
2527   for (i = 0; i < stream->stsd_entries_length; i++) {
2528     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2529     if (entry->rgb8_palette) {
2530       gst_memory_unref (entry->rgb8_palette);
2531       entry->rgb8_palette = NULL;
2532     }
2533     entry->sparse = FALSE;
2534   }
2535
2536   if (stream->stream_tags)
2537     gst_tag_list_unref (stream->stream_tags);
2538
2539   stream->stream_tags = gst_tag_list_new_empty ();
2540   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2541   g_free (stream->redirect_uri);
2542   stream->redirect_uri = NULL;
2543   stream->sent_eos = FALSE;
2544   stream->protected = FALSE;
2545   if (stream->protection_scheme_info) {
2546     if (stream->protection_scheme_type == FOURCC_cenc
2547         || stream->protection_scheme_type == FOURCC_cbcs) {
2548       QtDemuxCencSampleSetInfo *info =
2549           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2550       if (info->default_properties)
2551         gst_structure_free (info->default_properties);
2552       if (info->crypto_info)
2553         g_ptr_array_free (info->crypto_info, TRUE);
2554     }
2555     if (stream->protection_scheme_type == FOURCC_aavd) {
2556       QtDemuxAavdEncryptionInfo *info =
2557           (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
2558       if (info->default_properties)
2559         gst_structure_free (info->default_properties);
2560     }
2561     g_free (stream->protection_scheme_info);
2562     stream->protection_scheme_info = NULL;
2563   }
2564   stream->protection_scheme_type = 0;
2565   stream->protection_scheme_version = 0;
2566   g_queue_foreach (&stream->protection_scheme_event_queue,
2567       (GFunc) gst_event_unref, NULL);
2568   g_queue_clear (&stream->protection_scheme_event_queue);
2569   gst_qtdemux_stream_flush_segments_data (stream);
2570   gst_qtdemux_stream_flush_samples_data (stream);
2571 }
2572
2573 static void
2574 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2575 {
2576   gint i;
2577   gst_qtdemux_stream_clear (stream);
2578   for (i = 0; i < stream->stsd_entries_length; i++) {
2579     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2580     if (entry->caps) {
2581       gst_caps_unref (entry->caps);
2582       entry->caps = NULL;
2583     }
2584   }
2585   g_free (stream->stsd_entries);
2586   stream->stsd_entries = NULL;
2587   stream->stsd_entries_length = 0;
2588 }
2589
2590 static QtDemuxStream *
2591 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2592 {
2593   g_atomic_int_add (&stream->ref_count, 1);
2594
2595   return stream;
2596 }
2597
2598 static void
2599 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2600 {
2601   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2602     gst_qtdemux_stream_reset (stream);
2603     gst_tag_list_unref (stream->stream_tags);
2604     if (stream->pad) {
2605       GstQTDemux *demux = stream->demux;
2606       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2607       GST_OBJECT_LOCK (demux);
2608       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2609       GST_OBJECT_UNLOCK (demux);
2610     }
2611     g_free (stream->stream_id);
2612     g_free (stream);
2613   }
2614 }
2615
2616 static GstStateChangeReturn
2617 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2618 {
2619   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2620   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2621
2622   switch (transition) {
2623     case GST_STATE_CHANGE_READY_TO_PAUSED:
2624       gst_qtdemux_reset (qtdemux, TRUE);
2625       break;
2626     default:
2627       break;
2628   }
2629
2630   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2631
2632   switch (transition) {
2633     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2634       gst_qtdemux_reset (qtdemux, TRUE);
2635       break;
2636     }
2637     default:
2638       break;
2639   }
2640
2641   return result;
2642 }
2643
2644 static void
2645 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2646 {
2647   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2648
2649   g_return_if_fail (GST_IS_CONTEXT (context));
2650
2651   if (gst_context_has_context_type (context,
2652           "drm-preferred-decryption-system-id")) {
2653     const GstStructure *s;
2654
2655     s = gst_context_get_structure (context);
2656     g_free (qtdemux->preferred_protection_system_id);
2657     qtdemux->preferred_protection_system_id =
2658         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2659     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2660         qtdemux->preferred_protection_system_id);
2661   }
2662
2663   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2664 }
2665
2666 static void
2667 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2668 {
2669   /* counts as header data */
2670   qtdemux->header_size += length;
2671
2672   /* only consider at least a sufficiently complete ftyp atom */
2673   if (length >= 20) {
2674     GstBuffer *buf;
2675
2676     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2677     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2678         GST_FOURCC_ARGS (qtdemux->major_brand));
2679     if (qtdemux->comp_brands)
2680       gst_buffer_unref (qtdemux->comp_brands);
2681     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2682     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2683   }
2684 }
2685
2686 static void
2687 qtdemux_update_default_sample_cenc_settings (GstQTDemux * qtdemux,
2688     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted,
2689     guint32 protection_scheme_type, guint8 iv_size, const guint8 * kid,
2690     guint crypt_byte_block, guint skip_byte_block, guint8 constant_iv_size,
2691     const guint8 * constant_iv)
2692 {
2693   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2694   gst_buffer_fill (kid_buf, 0, kid, 16);
2695   if (info->default_properties)
2696     gst_structure_free (info->default_properties);
2697   info->default_properties =
2698       gst_structure_new ("application/x-cenc",
2699       "iv_size", G_TYPE_UINT, iv_size,
2700       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2701       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2702   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2703       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2704   gst_buffer_unref (kid_buf);
2705   if (protection_scheme_type == FOURCC_cbcs) {
2706     if (crypt_byte_block != 0 || skip_byte_block != 0) {
2707       gst_structure_set (info->default_properties, "crypt_byte_block",
2708           G_TYPE_UINT, crypt_byte_block, "skip_byte_block", G_TYPE_UINT,
2709           skip_byte_block, NULL);
2710     }
2711     if (constant_iv != NULL) {
2712       GstBuffer *constant_iv_buf =
2713           gst_buffer_new_allocate (NULL, constant_iv_size, NULL);
2714       gst_buffer_fill (constant_iv_buf, 0, constant_iv, constant_iv_size);
2715       gst_structure_set (info->default_properties, "constant_iv_size",
2716           G_TYPE_UINT, constant_iv_size, "iv", GST_TYPE_BUFFER, constant_iv_buf,
2717           NULL);
2718       gst_buffer_unref (constant_iv_buf);
2719     }
2720     gst_structure_set (info->default_properties, "cipher-mode",
2721         G_TYPE_STRING, "cbcs", NULL);
2722   } else {
2723     gst_structure_set (info->default_properties, "cipher-mode",
2724         G_TYPE_STRING, "cenc", NULL);
2725   }
2726 }
2727
2728 static gboolean
2729 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2730     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2731 {
2732   guint32 algorithm_id = 0;
2733   const guint8 *kid;
2734   gboolean is_encrypted = TRUE;
2735   guint8 iv_size = 8;
2736
2737   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2738     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2739     return FALSE;
2740   }
2741
2742   algorithm_id >>= 8;
2743   if (algorithm_id == 0) {
2744     is_encrypted = FALSE;
2745   } else if (algorithm_id == 1) {
2746     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2747   } else if (algorithm_id == 2) {
2748     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2749   }
2750
2751   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2752     return FALSE;
2753
2754   if (!gst_byte_reader_get_data (br, 16, &kid))
2755     return FALSE;
2756
2757   qtdemux_update_default_sample_cenc_settings (qtdemux, info,
2758       is_encrypted, FOURCC_cenc, iv_size, kid, 0, 0, 0, NULL);
2759   gst_structure_set (info->default_properties, "piff_algorithm_id",
2760       G_TYPE_UINT, algorithm_id, NULL);
2761   return TRUE;
2762 }
2763
2764
2765 static void
2766 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2767     guint offset)
2768 {
2769   GstByteReader br;
2770   guint8 version;
2771   guint32 flags = 0;
2772   guint i;
2773   guint iv_size = 8;
2774   QtDemuxStream *stream;
2775   GstStructure *structure;
2776   QtDemuxCencSampleSetInfo *ss_info = NULL;
2777   const gchar *system_id;
2778   gboolean uses_sub_sample_encryption = FALSE;
2779   guint32 sample_count;
2780
2781   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2782     return;
2783
2784   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2785
2786   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2787   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2788     GST_WARNING_OBJECT (qtdemux,
2789         "Attempting PIFF box parsing on an unencrypted stream.");
2790     return;
2791   }
2792
2793   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2794       G_TYPE_STRING, &system_id, NULL);
2795   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2796
2797   stream->protected = TRUE;
2798   stream->protection_scheme_type = FOURCC_cenc;
2799
2800   if (!stream->protection_scheme_info)
2801     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2802
2803   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2804   if (!ss_info->default_properties) {
2805     ss_info->default_properties =
2806         gst_structure_new ("application/x-cenc",
2807         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2808         NULL);
2809
2810   }
2811
2812   if (ss_info->crypto_info) {
2813     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2814     g_ptr_array_free (ss_info->crypto_info, TRUE);
2815     ss_info->crypto_info = NULL;
2816   }
2817
2818   /* skip UUID */
2819   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2820
2821   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2822     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2823     return;
2824   }
2825
2826   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2827     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2828     return;
2829   }
2830
2831   if ((flags & 0x000001)) {
2832     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2833             &br))
2834       return;
2835   } else if ((flags & 0x000002)) {
2836     uses_sub_sample_encryption = TRUE;
2837   }
2838
2839   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2840           &iv_size)) {
2841     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2842     return;
2843   }
2844
2845   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2846     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2847     return;
2848   }
2849
2850   ss_info->crypto_info =
2851       g_ptr_array_new_full (sample_count,
2852       (GDestroyNotify) qtdemux_gst_structure_free);
2853
2854   for (i = 0; i < sample_count; ++i) {
2855     GstStructure *properties;
2856     guint8 *data;
2857     GstBuffer *buf;
2858
2859     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2860     if (properties == NULL) {
2861       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2862       qtdemux->cenc_aux_sample_count = i;
2863       return;
2864     }
2865
2866     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2867       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2868       gst_structure_free (properties);
2869       qtdemux->cenc_aux_sample_count = i;
2870       return;
2871     }
2872     buf = gst_buffer_new_wrapped (data, iv_size);
2873     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2874     gst_buffer_unref (buf);
2875
2876     if (uses_sub_sample_encryption) {
2877       guint16 n_subsamples;
2878       const GValue *kid_buf_value;
2879
2880       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2881           || n_subsamples == 0) {
2882         GST_ERROR_OBJECT (qtdemux,
2883             "failed to get subsample count for sample %u", i);
2884         gst_structure_free (properties);
2885         qtdemux->cenc_aux_sample_count = i;
2886         return;
2887       }
2888       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2889       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2890         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2891             i);
2892         gst_structure_free (properties);
2893         qtdemux->cenc_aux_sample_count = i;
2894         return;
2895       }
2896       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2897
2898       kid_buf_value =
2899           gst_structure_get_value (ss_info->default_properties, "kid");
2900
2901       gst_structure_set (properties,
2902           "subsample_count", G_TYPE_UINT, n_subsamples,
2903           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2904       gst_structure_set_value (properties, "kid", kid_buf_value);
2905       gst_buffer_unref (buf);
2906     } else {
2907       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2908     }
2909
2910     g_ptr_array_add (ss_info->crypto_info, properties);
2911   }
2912
2913   qtdemux->cenc_aux_sample_count = sample_count;
2914 }
2915
2916 static void
2917 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2918 {
2919   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2920     0x97, 0xA9, 0x42, 0xE8,
2921     0x9C, 0x71, 0x99, 0x94,
2922     0x91, 0xE3, 0xAF, 0xAC
2923   };
2924   static const guint8 playready_uuid[] = {
2925     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2926     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2927   };
2928
2929   static const guint8 piff_sample_encryption_uuid[] = {
2930     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2931     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2932   };
2933
2934   guint offset;
2935
2936   /* counts as header data */
2937   qtdemux->header_size += length;
2938
2939   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2940
2941   if (length <= offset + 16) {
2942     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2943     return;
2944   }
2945
2946   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2947     GstBuffer *buf;
2948     GstTagList *taglist;
2949
2950     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2951         length - offset - 16, NULL);
2952     taglist = gst_tag_list_from_xmp_buffer (buf);
2953     gst_buffer_unref (buf);
2954
2955     /* make sure we have a usable taglist */
2956     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2957
2958     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2959
2960   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2961     int len;
2962     const gunichar2 *s_utf16;
2963     char *contents;
2964
2965     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2966     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2967     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2968     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2969
2970     g_free (contents);
2971
2972     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2973         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2974         (NULL));
2975   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2976     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2977   } else {
2978     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2979         GST_READ_UINT32_LE (buffer + offset),
2980         GST_READ_UINT32_LE (buffer + offset + 4),
2981         GST_READ_UINT32_LE (buffer + offset + 8),
2982         GST_READ_UINT32_LE (buffer + offset + 12));
2983   }
2984 }
2985
2986 static void
2987 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2988 {
2989   GstSidxParser sidx_parser;
2990   GstIsoffParserResult res;
2991   guint consumed;
2992
2993   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2994
2995   res =
2996       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2997       &consumed);
2998   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2999   if (res == GST_ISOFF_QT_PARSER_DONE) {
3000     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3001   }
3002   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3003 }
3004
3005 /* caller verifies at least 8 bytes in buf */
3006 static void
3007 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3008     guint64 * plength, guint32 * pfourcc)
3009 {
3010   guint64 length;
3011   guint32 fourcc;
3012
3013   length = QT_UINT32 (data);
3014   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3015   fourcc = QT_FOURCC (data + 4);
3016   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3017
3018   if (length == 0) {
3019     length = G_MAXUINT64;
3020   } else if (length == 1 && size >= 16) {
3021     /* this means we have an extended size, which is the 64 bit value of
3022      * the next 8 bytes */
3023     length = QT_UINT64 (data + 8);
3024     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3025   }
3026
3027   if (plength)
3028     *plength = length;
3029   if (pfourcc)
3030     *pfourcc = fourcc;
3031 }
3032
3033 static gboolean
3034 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3035 {
3036   guint32 version = 0;
3037   GstClockTime duration = 0;
3038
3039   if (!gst_byte_reader_get_uint32_be (br, &version))
3040     goto failed;
3041
3042   version >>= 24;
3043   if (version == 1) {
3044     if (!gst_byte_reader_get_uint64_be (br, &duration))
3045       goto failed;
3046   } else {
3047     guint32 dur = 0;
3048
3049     if (!gst_byte_reader_get_uint32_be (br, &dur))
3050       goto failed;
3051     duration = dur;
3052   }
3053
3054   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3055   qtdemux->duration = duration;
3056
3057   return TRUE;
3058
3059 failed:
3060   {
3061     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3062     return FALSE;
3063   }
3064 }
3065
3066 static gboolean
3067 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3068     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3069 {
3070   if (!stream->parsed_trex && qtdemux->moov_node) {
3071     GNode *mvex, *trex;
3072     GstByteReader trex_data;
3073
3074     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3075     if (mvex) {
3076       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3077           &trex_data);
3078       while (trex) {
3079         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3080
3081         /* skip version/flags */
3082         if (!gst_byte_reader_skip (&trex_data, 4))
3083           goto next;
3084         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3085           goto next;
3086         if (id != stream->track_id)
3087           goto next;
3088         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3089           goto next;
3090         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3091           goto next;
3092         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3093           goto next;
3094         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3095           goto next;
3096
3097         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3098             "duration %d,  size %d, flags 0x%x", stream->track_id,
3099             dur, size, flags);
3100
3101         stream->parsed_trex = TRUE;
3102         stream->def_sample_description_index = sdi;
3103         stream->def_sample_duration = dur;
3104         stream->def_sample_size = size;
3105         stream->def_sample_flags = flags;
3106
3107       next:
3108         /* iterate all siblings */
3109         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3110             &trex_data);
3111       }
3112     }
3113   }
3114
3115   *ds_duration = stream->def_sample_duration;
3116   *ds_size = stream->def_sample_size;
3117   *ds_flags = stream->def_sample_flags;
3118
3119   /* even then, above values are better than random ... */
3120   if (G_UNLIKELY (!stream->parsed_trex)) {
3121     GST_WARNING_OBJECT (qtdemux,
3122         "failed to find fragment defaults for stream %d", stream->track_id);
3123     return FALSE;
3124   }
3125
3126   return TRUE;
3127 }
3128
3129 /* This method should be called whenever a more accurate duration might
3130  * have been found. It will update all relevant variables if/where needed
3131  */
3132 static void
3133 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3134 {
3135   guint i;
3136   guint64 movdur;
3137   GstClockTime prevdur;
3138
3139   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3140
3141   if (movdur > qtdemux->duration) {
3142     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3143     GST_DEBUG_OBJECT (qtdemux,
3144         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3145         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3146     qtdemux->duration = movdur;
3147     GST_DEBUG_OBJECT (qtdemux,
3148         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3149         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3150         GST_TIME_ARGS (qtdemux->segment.stop));
3151     if (qtdemux->segment.duration == prevdur) {
3152       /* If the current segment has duration/stop identical to previous duration
3153        * update them also (because they were set at that point in time with
3154        * the wrong duration */
3155       /* We convert the value *from* the timescale version to avoid rounding errors */
3156       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3157       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3158       qtdemux->segment.duration = fixeddur;
3159       qtdemux->segment.stop = fixeddur;
3160     }
3161   }
3162
3163   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3164     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3165
3166     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3167     if (movdur > stream->duration) {
3168       GST_DEBUG_OBJECT (qtdemux,
3169           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3170           GST_TIME_ARGS (duration));
3171       stream->duration = movdur;
3172       /* internal duration tracking state has been updated above, so */
3173       /* preserve an open-ended dummy segment rather than repeatedly updating
3174        * it and spamming downstream accordingly with segment events */
3175       /* also mangle the edit list end time when fragmented with a single edit
3176        * list that may only cover any non-fragmented data */
3177       if ((stream->dummy_segment ||
3178               (qtdemux->fragmented && stream->n_segments == 1)) &&
3179           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3180         /* Update all dummy values to new duration */
3181         stream->segments[0].stop_time = duration;
3182         stream->segments[0].duration = duration;
3183         stream->segments[0].media_stop = duration;
3184
3185         /* let downstream know we possibly have a new stop time */
3186         if (stream->segment_index != -1) {
3187           GstClockTime pos;
3188
3189           if (qtdemux->segment.rate >= 0) {
3190             pos = stream->segment.start;
3191           } else {
3192             pos = stream->segment.stop;
3193           }
3194
3195           gst_qtdemux_stream_update_segment (qtdemux, stream,
3196               stream->segment_index, pos, NULL, NULL);
3197         }
3198       }
3199     }
3200   }
3201 }
3202
3203 static gboolean
3204 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3205     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3206     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3207     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3208     gboolean has_tfdt)
3209 {
3210   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3211   guint64 timestamp;
3212   gint32 data_offset = 0;
3213   guint32 flags = 0, first_flags = 0, samples_count = 0;
3214   gint i;
3215   guint8 *data;
3216   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3217   QtDemuxSample *sample;
3218   gboolean ismv = FALSE;
3219   gint64 initial_offset;
3220
3221   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3222       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3223       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3224       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3225
3226   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3227     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3228     return TRUE;
3229   }
3230
3231   /* presence of stss or not can't really tell us much,
3232    * and flags and so on tend to be marginally reliable in these files */
3233   if (stream->subtype == FOURCC_soun) {
3234     GST_DEBUG_OBJECT (qtdemux,
3235         "sound track in fragmented file; marking all keyframes");
3236     stream->all_keyframe = TRUE;
3237   }
3238
3239   if (!gst_byte_reader_skip (trun, 1) ||
3240       !gst_byte_reader_get_uint24_be (trun, &flags))
3241     goto fail;
3242
3243   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3244     goto fail;
3245
3246   if (flags & TR_DATA_OFFSET) {
3247     /* note this is really signed */
3248     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3249       goto fail;
3250     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3251     /* default base offset = first byte of moof */
3252     if (*base_offset == -1) {
3253       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3254       *base_offset = moof_offset;
3255     }
3256     *running_offset = *base_offset + data_offset;
3257   } else {
3258     /* if no offset at all, that would mean data starts at moof start,
3259      * which is a bit wrong and is ismv crappy way, so compensate
3260      * assuming data is in mdat following moof */
3261     if (*base_offset == -1) {
3262       *base_offset = moof_offset + moof_length + 8;
3263       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3264       ismv = TRUE;
3265     }
3266     if (*running_offset == -1)
3267       *running_offset = *base_offset;
3268   }
3269
3270   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3271       *running_offset);
3272   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3273       data_offset, flags, samples_count);
3274
3275   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3276     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3277       GST_DEBUG_OBJECT (qtdemux,
3278           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3279       flags ^= TR_FIRST_SAMPLE_FLAGS;
3280     } else {
3281       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3282         goto fail;
3283       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3284     }
3285   }
3286
3287   /* FIXME ? spec says other bits should also be checked to determine
3288    * entry size (and prefix size for that matter) */
3289   entry_size = 0;
3290   dur_offset = size_offset = 0;
3291   if (flags & TR_SAMPLE_DURATION) {
3292     GST_LOG_OBJECT (qtdemux, "entry duration present");
3293     dur_offset = entry_size;
3294     entry_size += 4;
3295   }
3296   if (flags & TR_SAMPLE_SIZE) {
3297     GST_LOG_OBJECT (qtdemux, "entry size present");
3298     size_offset = entry_size;
3299     entry_size += 4;
3300   }
3301   if (flags & TR_SAMPLE_FLAGS) {
3302     GST_LOG_OBJECT (qtdemux, "entry flags present");
3303     flags_offset = entry_size;
3304     entry_size += 4;
3305   }
3306   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3307     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3308     ct_offset = entry_size;
3309     entry_size += 4;
3310   }
3311
3312   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3313     goto fail;
3314   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3315
3316   if (stream->n_samples + samples_count >=
3317       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3318     goto index_too_big;
3319
3320   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3321       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3322       (stream->n_samples + samples_count) *
3323       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3324
3325   /* create a new array of samples if it's the first sample parsed */
3326   if (stream->n_samples == 0) {
3327     g_assert (stream->samples == NULL);
3328     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3329     /* or try to reallocate it with space enough to insert the new samples */
3330   } else
3331     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3332         stream->n_samples + samples_count);
3333   if (stream->samples == NULL)
3334     goto out_of_memory;
3335
3336   if (qtdemux->fragment_start != -1) {
3337     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3338     qtdemux->fragment_start = -1;
3339   } else {
3340     if (stream->n_samples == 0) {
3341       if (decode_ts > 0) {
3342         timestamp = decode_ts;
3343       } else if (stream->pending_seek != NULL) {
3344         /* if we don't have a timestamp from a tfdt box, we'll use the one
3345          * from the mfra seek table */
3346         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3347             GST_TIME_ARGS (stream->pending_seek->ts));
3348
3349         /* FIXME: this is not fully correct, the timestamp refers to the random
3350          * access sample refered to in the tfra entry, which may not necessarily
3351          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3352         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3353       } else {
3354         timestamp = 0;
3355       }
3356
3357       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3358       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3359           GST_TIME_ARGS (gst_ts));
3360     } else {
3361       /* subsequent fragments extend stream */
3362       timestamp =
3363           stream->samples[stream->n_samples - 1].timestamp +
3364           stream->samples[stream->n_samples - 1].duration;
3365
3366       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3367        * difference (1 sec.) between decode_ts and timestamp, prefer the
3368        * former */
3369       if (has_tfdt && !qtdemux->upstream_format_is_time
3370           && ABSDIFF (decode_ts, timestamp) >
3371           MAX (stream->duration_last_moof / 2,
3372               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3373         GST_INFO_OBJECT (qtdemux,
3374             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3375             ") are significantly different (more than %" GST_TIME_FORMAT
3376             "), using decode_ts",
3377             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3378             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3379             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3380                     MAX (stream->duration_last_moof / 2,
3381                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3382         timestamp = decode_ts;
3383       }
3384
3385       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3386       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3387           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3388     }
3389   }
3390
3391   initial_offset = *running_offset;
3392
3393   sample = stream->samples + stream->n_samples;
3394   for (i = 0; i < samples_count; i++) {
3395     guint32 dur, size, sflags, ct;
3396
3397     /* first read sample data */
3398     if (flags & TR_SAMPLE_DURATION) {
3399       dur = QT_UINT32 (data + dur_offset);
3400     } else {
3401       dur = d_sample_duration;
3402     }
3403     if (flags & TR_SAMPLE_SIZE) {
3404       size = QT_UINT32 (data + size_offset);
3405     } else {
3406       size = d_sample_size;
3407     }
3408     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3409       if (i == 0) {
3410         sflags = first_flags;
3411       } else {
3412         sflags = d_sample_flags;
3413       }
3414     } else if (flags & TR_SAMPLE_FLAGS) {
3415       sflags = QT_UINT32 (data + flags_offset);
3416     } else {
3417       sflags = d_sample_flags;
3418     }
3419     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3420       ct = QT_UINT32 (data + ct_offset);
3421     } else {
3422       ct = 0;
3423     }
3424     data += entry_size;
3425
3426     /* fill the sample information */
3427     sample->offset = *running_offset;
3428     sample->pts_offset = ct;
3429     sample->size = size;
3430     sample->timestamp = timestamp;
3431     sample->duration = dur;
3432     /* sample-is-difference-sample */
3433     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3434      * now idea how it relates to bitfield other than massive LE/BE confusion */
3435     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3436     *running_offset += size;
3437     timestamp += dur;
3438     stream->duration_moof += dur;
3439     sample++;
3440   }
3441
3442   /* Update total duration if needed */
3443   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3444
3445   /* Pre-emptively figure out size of mdat based on trun information.
3446    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3447    * size, else we will still be able to use this when dealing with gap'ed
3448    * input */
3449   qtdemux->mdatleft = *running_offset - initial_offset;
3450   qtdemux->mdatoffset = initial_offset;
3451   qtdemux->mdatsize = qtdemux->mdatleft;
3452
3453   stream->n_samples += samples_count;
3454   stream->n_samples_moof += samples_count;
3455
3456   if (stream->pending_seek != NULL)
3457     stream->pending_seek = NULL;
3458
3459   return TRUE;
3460
3461 fail:
3462   {
3463     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3464     return FALSE;
3465   }
3466 out_of_memory:
3467   {
3468     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3469         stream->n_samples);
3470     return FALSE;
3471   }
3472 index_too_big:
3473   {
3474     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3475         "be larger than %uMB (broken file?)", stream->n_samples,
3476         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3477     return FALSE;
3478   }
3479 }
3480
3481 /* find stream with @id */
3482 static inline QtDemuxStream *
3483 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3484 {
3485   QtDemuxStream *stream;
3486   gint i;
3487
3488   /* check */
3489   if (G_UNLIKELY (!id)) {
3490     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3491     return NULL;
3492   }
3493
3494   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3495     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3496     if (stream->track_id == id)
3497       return stream;
3498   }
3499   if (qtdemux->mss_mode) {
3500     /* mss should have only 1 stream anyway */
3501     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3502   }
3503
3504   return NULL;
3505 }
3506
3507 static gboolean
3508 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3509     guint32 * fragment_number)
3510 {
3511   if (!gst_byte_reader_skip (mfhd, 4))
3512     goto fail;
3513   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3514     goto fail;
3515   return TRUE;
3516 fail:
3517   {
3518     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3519     return FALSE;
3520   }
3521 }
3522
3523 static gboolean
3524 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3525     QtDemuxStream ** stream, guint32 * default_sample_duration,
3526     guint32 * default_sample_size, guint32 * default_sample_flags,
3527     gint64 * base_offset)
3528 {
3529   guint32 flags = 0;
3530   guint32 track_id = 0;
3531
3532   if (!gst_byte_reader_skip (tfhd, 1) ||
3533       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3534     goto invalid_track;
3535
3536   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3537     goto invalid_track;
3538
3539   *stream = qtdemux_find_stream (qtdemux, track_id);
3540   if (G_UNLIKELY (!*stream))
3541     goto unknown_stream;
3542
3543   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3544     *base_offset = qtdemux->moof_offset;
3545
3546   if (flags & TF_BASE_DATA_OFFSET)
3547     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3548       goto invalid_track;
3549
3550   /* obtain stream defaults */
3551   qtdemux_parse_trex (qtdemux, *stream,
3552       default_sample_duration, default_sample_size, default_sample_flags);
3553
3554   (*stream)->stsd_sample_description_id =
3555       (*stream)->def_sample_description_index - 1;
3556
3557   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3558     guint32 sample_description_index;
3559     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3560       goto invalid_track;
3561     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3562   }
3563
3564   if (qtdemux->mss_mode) {
3565     /* mss has no stsd entry */
3566     (*stream)->stsd_sample_description_id = 0;
3567   }
3568
3569   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3570     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3571       goto invalid_track;
3572
3573   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3574     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3575       goto invalid_track;
3576
3577   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3578     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3579       goto invalid_track;
3580
3581   return TRUE;
3582
3583 invalid_track:
3584   {
3585     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3586     return FALSE;
3587   }
3588 unknown_stream:
3589   {
3590     GST_DEBUG_OBJECT (qtdemux, "unknown stream (%u) in tfhd", track_id);
3591     return TRUE;
3592   }
3593 }
3594
3595 static gboolean
3596 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3597     guint64 * decode_time)
3598 {
3599   guint32 version = 0;
3600
3601   if (!gst_byte_reader_get_uint32_be (br, &version))
3602     return FALSE;
3603
3604   version >>= 24;
3605   if (version == 1) {
3606     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3607       goto failed;
3608   } else {
3609     guint32 dec_time = 0;
3610     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3611       goto failed;
3612     *decode_time = dec_time;
3613   }
3614
3615   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3616       *decode_time);
3617
3618   return TRUE;
3619
3620 failed:
3621   {
3622     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3623     return FALSE;
3624   }
3625 }
3626
3627 /* Returns a pointer to a GstStructure containing the properties of
3628  * the stream sample identified by @sample_index. The caller must unref
3629  * the returned object after use. Returns NULL if unsuccessful. */
3630 static GstStructure *
3631 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3632     QtDemuxStream * stream, guint sample_index)
3633 {
3634   QtDemuxCencSampleSetInfo *info = NULL;
3635
3636   g_return_val_if_fail (stream != NULL, NULL);
3637   g_return_val_if_fail (stream->protected, NULL);
3638   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3639
3640   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3641
3642   /* Currently, cenc properties for groups of samples are not supported, so
3643    * simply return a copy of the default sample properties */
3644   return gst_structure_copy (info->default_properties);
3645 }
3646
3647 /* Parses the sizes of sample auxiliary information contained within a stream,
3648  * as given in a saiz box. Returns array of sample_count guint8 size values,
3649  * or NULL on failure */
3650 static guint8 *
3651 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3652     GstByteReader * br, guint32 * sample_count)
3653 {
3654   guint32 flags = 0;
3655   guint8 *info_sizes;
3656   guint8 default_info_size;
3657
3658   g_return_val_if_fail (qtdemux != NULL, NULL);
3659   g_return_val_if_fail (stream != NULL, NULL);
3660   g_return_val_if_fail (br != NULL, NULL);
3661   g_return_val_if_fail (sample_count != NULL, NULL);
3662
3663   if (!gst_byte_reader_get_uint32_be (br, &flags))
3664     return NULL;
3665
3666   if (flags & 0x1) {
3667     /* aux_info_type and aux_info_type_parameter are ignored */
3668     if (!gst_byte_reader_skip (br, 8))
3669       return NULL;
3670   }
3671
3672   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3673     return NULL;
3674   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3675
3676   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3677     return NULL;
3678   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3679
3680
3681   if (default_info_size == 0) {
3682     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3683       return NULL;
3684     }
3685   } else {
3686     info_sizes = g_new (guint8, *sample_count);
3687     memset (info_sizes, default_info_size, *sample_count);
3688   }
3689
3690   return info_sizes;
3691 }
3692
3693 /* Parses the offset of sample auxiliary information contained within a stream,
3694  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3695 static gboolean
3696 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3697     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3698     guint64 * offset)
3699 {
3700   guint8 version = 0;
3701   guint32 flags = 0;
3702   guint32 aux_info_type = 0;
3703   guint32 aux_info_type_parameter = 0;
3704   guint32 entry_count;
3705   guint32 off_32;
3706   guint64 off_64;
3707   const guint8 *aux_info_type_data = NULL;
3708
3709   g_return_val_if_fail (qtdemux != NULL, FALSE);
3710   g_return_val_if_fail (stream != NULL, FALSE);
3711   g_return_val_if_fail (br != NULL, FALSE);
3712   g_return_val_if_fail (offset != NULL, FALSE);
3713
3714   if (!gst_byte_reader_get_uint8 (br, &version))
3715     return FALSE;
3716
3717   if (!gst_byte_reader_get_uint24_be (br, &flags))
3718     return FALSE;
3719
3720   if (flags & 0x1) {
3721
3722     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3723       return FALSE;
3724     aux_info_type = QT_FOURCC (aux_info_type_data);
3725
3726     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3727       return FALSE;
3728   } else if (stream->protected) {
3729     aux_info_type = stream->protection_scheme_type;
3730   } else {
3731     aux_info_type = CUR_STREAM (stream)->fourcc;
3732   }
3733
3734   if (info_type)
3735     *info_type = aux_info_type;
3736   if (info_type_parameter)
3737     *info_type_parameter = aux_info_type_parameter;
3738
3739   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3740       "aux_info_type_parameter:  %#06x",
3741       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3742
3743   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3744     return FALSE;
3745
3746   if (entry_count != 1) {
3747     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3748     return FALSE;
3749   }
3750
3751   if (version == 0) {
3752     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3753       return FALSE;
3754     *offset = (guint64) off_32;
3755   } else {
3756     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3757       return FALSE;
3758     *offset = off_64;
3759   }
3760
3761   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3762   return TRUE;
3763 }
3764
3765 static void
3766 qtdemux_gst_structure_free (GstStructure * gststructure)
3767 {
3768   if (gststructure) {
3769     gst_structure_free (gststructure);
3770   }
3771 }
3772
3773 /* Parses auxiliary information relating to samples protected using
3774  * Common Encryption (cenc); the format of this information
3775  * is defined in ISO/IEC 23001-7. Returns TRUE if successful; FALSE
3776  * otherwise. */
3777 static gboolean
3778 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3779     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3780 {
3781   QtDemuxCencSampleSetInfo *ss_info = NULL;
3782   guint8 size;
3783   gint i;
3784   GPtrArray *old_crypto_info = NULL;
3785   guint old_entries = 0;
3786
3787   g_return_val_if_fail (qtdemux != NULL, FALSE);
3788   g_return_val_if_fail (stream != NULL, FALSE);
3789   g_return_val_if_fail (br != NULL, FALSE);
3790   g_return_val_if_fail (stream->protected, FALSE);
3791   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3792
3793   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3794
3795   if (ss_info->crypto_info) {
3796     old_crypto_info = ss_info->crypto_info;
3797     /* Count number of non-null entries remaining at the tail end */
3798     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3799       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3800         break;
3801       old_entries++;
3802     }
3803   }
3804
3805   ss_info->crypto_info =
3806       g_ptr_array_new_full (sample_count + old_entries,
3807       (GDestroyNotify) qtdemux_gst_structure_free);
3808
3809   /* We preserve old entries because we parse the next moof in advance
3810    * of consuming all samples from the previous moof, and otherwise
3811    * we'd discard the corresponding crypto info for the samples
3812    * from the previous fragment. */
3813   if (old_entries) {
3814     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3815         old_entries);
3816     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3817       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3818               i));
3819       g_ptr_array_index (old_crypto_info, i) = NULL;
3820     }
3821   }
3822
3823   if (old_crypto_info) {
3824     /* Everything now belongs to the new array */
3825     g_ptr_array_free (old_crypto_info, TRUE);
3826   }
3827
3828   for (i = 0; i < sample_count; ++i) {
3829     GstStructure *properties;
3830     guint16 n_subsamples = 0;
3831     guint8 *data;
3832     guint iv_size;
3833     GstBuffer *buf;
3834     gboolean could_read_iv;
3835
3836     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3837     if (properties == NULL) {
3838       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3839       return FALSE;
3840     }
3841     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3842       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3843       gst_structure_free (properties);
3844       return FALSE;
3845     }
3846     could_read_iv =
3847         iv_size > 0 ? gst_byte_reader_dup_data (br, iv_size, &data) : FALSE;
3848     if (could_read_iv) {
3849       buf = gst_buffer_new_wrapped (data, iv_size);
3850       gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3851       gst_buffer_unref (buf);
3852     } else if (stream->protection_scheme_type == FOURCC_cbcs) {
3853       const GValue *constant_iv_size_value =
3854           gst_structure_get_value (properties, "constant_iv_size");
3855       const GValue *constant_iv_value =
3856           gst_structure_get_value (properties, "iv");
3857       if (constant_iv_size_value == NULL || constant_iv_value == NULL) {
3858         GST_ERROR_OBJECT (qtdemux, "failed to get constant_iv");
3859         gst_structure_free (properties);
3860         return FALSE;
3861       }
3862       gst_structure_set_value (properties, "iv_size", constant_iv_size_value);
3863       gst_structure_remove_field (properties, "constant_iv_size");
3864     } else if (stream->protection_scheme_type == FOURCC_cenc) {
3865       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3866       gst_structure_free (properties);
3867       return FALSE;
3868     }
3869     size = info_sizes[i];
3870     if (size > iv_size) {
3871       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3872           || !(n_subsamples > 0)) {
3873         gst_structure_free (properties);
3874         GST_ERROR_OBJECT (qtdemux,
3875             "failed to get subsample count for sample %u", i);
3876         return FALSE;
3877       }
3878       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3879       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3880         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3881             i);
3882         gst_structure_free (properties);
3883         return FALSE;
3884       }
3885       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3886       if (!buf) {
3887         gst_structure_free (properties);
3888         return FALSE;
3889       }
3890       gst_structure_set (properties,
3891           "subsample_count", G_TYPE_UINT, n_subsamples,
3892           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3893       gst_buffer_unref (buf);
3894     } else {
3895       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3896     }
3897     g_ptr_array_add (ss_info->crypto_info, properties);
3898   }
3899   return TRUE;
3900 }
3901
3902 /* Converts a UUID in raw byte form to a string representation, as defined in
3903  * RFC 4122. The caller takes ownership of the returned string and is
3904  * responsible for freeing it after use. */
3905 static gchar *
3906 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3907 {
3908   const guint8 *uuid = (const guint8 *) uuid_bytes;
3909
3910   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3911       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3912       uuid[0], uuid[1], uuid[2], uuid[3],
3913       uuid[4], uuid[5], uuid[6], uuid[7],
3914       uuid[8], uuid[9], uuid[10], uuid[11],
3915       uuid[12], uuid[13], uuid[14], uuid[15]);
3916 }
3917
3918 /* Parses a Protection System Specific Header box (pssh), as defined in the
3919  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3920  * information needed by a specific content protection system in order to
3921  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3922  * otherwise. */
3923 static gboolean
3924 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3925 {
3926   gchar *sysid_string;
3927   guint32 pssh_size = QT_UINT32 (node->data);
3928   GstBuffer *pssh = NULL;
3929   GstEvent *event = NULL;
3930   guint32 parent_box_type;
3931   gint i;
3932
3933   if (G_UNLIKELY (pssh_size < 32U)) {
3934     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3935     return FALSE;
3936   }
3937
3938   sysid_string =
3939       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3940
3941   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3942
3943   pssh = gst_buffer_new_memdup (node->data, pssh_size);
3944   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3945       gst_buffer_get_size (pssh));
3946
3947   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3948
3949   /* Push an event containing the pssh box onto the queues of all streams. */
3950   event = gst_event_new_protection (sysid_string, pssh,
3951       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3952   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3953     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3954     GST_TRACE_OBJECT (qtdemux,
3955         "adding protection event for stream %s and system %s",
3956         stream->stream_id, sysid_string);
3957     g_queue_push_tail (&stream->protection_scheme_event_queue,
3958         gst_event_ref (event));
3959   }
3960   g_free (sysid_string);
3961   gst_event_unref (event);
3962   gst_buffer_unref (pssh);
3963   return TRUE;
3964 }
3965
3966 static gboolean
3967 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3968     guint64 moof_offset, QtDemuxStream * stream)
3969 {
3970   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3971   GNode *uuid_node;
3972   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3973   GNode *saiz_node, *saio_node, *pssh_node;
3974   GstByteReader saiz_data, saio_data;
3975   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3976   gint64 base_offset, running_offset;
3977   guint32 frag_num;
3978   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3979
3980   /* NOTE @stream ignored */
3981
3982   moof_node = g_node_new ((guint8 *) buffer);
3983   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3984   qtdemux_node_dump (qtdemux, moof_node);
3985
3986   /* Get fragment number from mfhd and check it's valid */
3987   mfhd_node =
3988       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3989   if (mfhd_node == NULL)
3990     goto missing_mfhd;
3991   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3992     goto fail;
3993   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3994
3995   /* unknown base_offset to start with */
3996   base_offset = running_offset = -1;
3997   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3998   while (traf_node) {
3999     guint64 decode_time = 0;
4000
4001     /* Fragment Header node */
4002     tfhd_node =
4003         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4004         &tfhd_data);
4005     if (!tfhd_node)
4006       goto missing_tfhd;
4007     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4008             &ds_size, &ds_flags, &base_offset))
4009       goto missing_tfhd;
4010
4011     /* The following code assumes at most a single set of sample auxiliary
4012      * data in the fragment (consisting of a saiz box and a corresponding saio
4013      * box); in theory, however, there could be multiple sets of sample
4014      * auxiliary data in a fragment. */
4015     saiz_node =
4016         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4017         &saiz_data);
4018     if (saiz_node) {
4019       guint32 info_type = 0;
4020       guint64 offset = 0;
4021       guint32 info_type_parameter = 0;
4022
4023       g_free (qtdemux->cenc_aux_info_sizes);
4024
4025       qtdemux->cenc_aux_info_sizes =
4026           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4027           &qtdemux->cenc_aux_sample_count);
4028       if (qtdemux->cenc_aux_info_sizes == NULL) {
4029         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4030         goto fail;
4031       }
4032       saio_node =
4033           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4034           &saio_data);
4035       if (!saio_node) {
4036         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4037         g_free (qtdemux->cenc_aux_info_sizes);
4038         qtdemux->cenc_aux_info_sizes = NULL;
4039         goto fail;
4040       }
4041
4042       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4043                   &info_type, &info_type_parameter, &offset))) {
4044         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4045         g_free (qtdemux->cenc_aux_info_sizes);
4046         qtdemux->cenc_aux_info_sizes = NULL;
4047         goto fail;
4048       }
4049       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4050         offset += (guint64) (base_offset - qtdemux->moof_offset);
4051       if ((info_type == FOURCC_cenc || info_type == FOURCC_cbcs)
4052           && info_type_parameter == 0U) {
4053         GstByteReader br;
4054         if (offset > length) {
4055           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4056           qtdemux->cenc_aux_info_offset = offset;
4057         } else {
4058           gst_byte_reader_init (&br, buffer + offset, length - offset);
4059           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4060                   qtdemux->cenc_aux_info_sizes,
4061                   qtdemux->cenc_aux_sample_count)) {
4062             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4063             g_free (qtdemux->cenc_aux_info_sizes);
4064             qtdemux->cenc_aux_info_sizes = NULL;
4065             goto fail;
4066           }
4067         }
4068       }
4069     }
4070
4071     tfdt_node =
4072         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4073         &tfdt_data);
4074     if (tfdt_node) {
4075       /* We'll use decode_time to interpolate timestamps
4076        * in case the input timestamps are missing */
4077       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4078
4079       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4080           " (%" GST_TIME_FORMAT ")", decode_time,
4081           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4082                   decode_time) : GST_CLOCK_TIME_NONE));
4083
4084       /* Discard the fragment buffer timestamp info to avoid using it.
4085        * Rely on tfdt instead as it is more accurate than the timestamp
4086        * that is fetched from a manifest/playlist and is usually
4087        * less accurate. */
4088       qtdemux->fragment_start = -1;
4089     }
4090
4091     if (G_UNLIKELY (!stream)) {
4092       /* we lost track of offset, we'll need to regain it,
4093        * but can delay complaining until later or avoid doing so altogether */
4094       base_offset = -2;
4095       goto next;
4096     }
4097     if (G_UNLIKELY (base_offset < -1))
4098       goto lost_offset;
4099
4100     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4101
4102     if (!qtdemux->pullbased) {
4103       /* Sample tables can grow enough to be problematic if the system memory
4104        * is very low (e.g. embedded devices) and the videos very long
4105        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4106        * Fortunately, we can easily discard them for each new fragment when
4107        * we know qtdemux will not receive seeks outside of the current fragment.
4108        * adaptivedemux honors this assumption.
4109        * This optimization is also useful for applications that use qtdemux as
4110        * a push-based simple demuxer, like Media Source Extensions. */
4111       gst_qtdemux_stream_flush_samples_data (stream);
4112     }
4113
4114     /* initialise moof sample data */
4115     stream->n_samples_moof = 0;
4116     stream->duration_last_moof = stream->duration_moof;
4117     stream->duration_moof = 0;
4118
4119     /* Track Run node */
4120     trun_node =
4121         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4122         &trun_data);
4123     while (trun_node) {
4124       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4125           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4126           &running_offset, decode_time, (tfdt_node != NULL));
4127       /* iterate all siblings */
4128       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4129           &trun_data);
4130     }
4131
4132     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4133     if (uuid_node) {
4134       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4135       guint32 box_length = QT_UINT32 (uuid_buffer);
4136
4137       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4138     }
4139
4140     /* if no new base_offset provided for next traf,
4141      * base is end of current traf */
4142     base_offset = running_offset;
4143     running_offset = -1;
4144
4145     if (stream->n_samples_moof && stream->duration_moof)
4146       stream->new_caps = TRUE;
4147
4148   next:
4149     /* iterate all siblings */
4150     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4151   }
4152
4153   /* parse any protection system info */
4154   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4155   while (pssh_node) {
4156     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4157     qtdemux_parse_pssh (qtdemux, pssh_node);
4158     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4159   }
4160
4161   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4162       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4163       && min_dts != 0) {
4164     /* Unless the user has explicitly requested another seek, perform an
4165      * internal seek to the time specified in the tfdt.
4166      *
4167      * This way if the user opens a file where the first tfdt is 1 hour
4168      * into the presentation, they will not have to wait 1 hour for run
4169      * time to catch up and actual playback to start. */
4170     gint i;
4171
4172     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4173         "performing an internal seek to %" GST_TIME_FORMAT,
4174         GST_TIME_ARGS (min_dts));
4175
4176     qtdemux->segment.start = min_dts;
4177     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4178
4179     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4180       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4181       stream->time_position = min_dts;
4182     }
4183
4184     /* Before this code was run a segment was already sent when the moov was
4185      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4186      * be emitted after a moov, and we can emit a second segment anyway for
4187      * special cases like this. */
4188     qtdemux->need_segment = TRUE;
4189   }
4190
4191   qtdemux->first_moof_already_parsed = TRUE;
4192
4193   g_node_destroy (moof_node);
4194   return TRUE;
4195
4196 missing_tfhd:
4197   {
4198     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4199     goto fail;
4200   }
4201 missing_mfhd:
4202   {
4203     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4204     goto fail;
4205   }
4206 lost_offset:
4207   {
4208     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4209     goto fail;
4210   }
4211 fail:
4212   {
4213     g_node_destroy (moof_node);
4214     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4215         (_("This file is corrupt and cannot be played.")), (NULL));
4216     return FALSE;
4217   }
4218 }
4219
4220 #if 0
4221 /* might be used if some day we actually use mfra & co
4222  * for random access to fragments,
4223  * but that will require quite some modifications and much less relying
4224  * on a sample array */
4225 #endif
4226
4227 static gboolean
4228 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4229 {
4230   QtDemuxStream *stream;
4231   guint32 ver_flags, track_id, len, num_entries, i;
4232   guint value_size, traf_size, trun_size, sample_size;
4233   guint64 time = 0, moof_offset = 0;
4234 #if 0
4235   GstBuffer *buf = NULL;
4236   GstFlowReturn ret;
4237 #endif
4238   GstByteReader tfra;
4239
4240   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4241
4242   if (!gst_byte_reader_skip (&tfra, 8))
4243     return FALSE;
4244
4245   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4246     return FALSE;
4247
4248   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4249       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4250       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4251     return FALSE;
4252
4253   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4254
4255   stream = qtdemux_find_stream (qtdemux, track_id);
4256   if (stream == NULL)
4257     goto unknown_trackid;
4258
4259   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4260   sample_size = (len & 3) + 1;
4261   trun_size = ((len & 12) >> 2) + 1;
4262   traf_size = ((len & 48) >> 4) + 1;
4263
4264   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4265       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4266
4267   if (num_entries == 0)
4268     goto no_samples;
4269
4270   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4271           value_size + value_size + traf_size + trun_size + sample_size))
4272     goto corrupt_file;
4273
4274   g_free (stream->ra_entries);
4275   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4276   stream->n_ra_entries = num_entries;
4277
4278   for (i = 0; i < num_entries; i++) {
4279     qt_atom_parser_get_offset (&tfra, value_size, &time);
4280     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4281     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4282     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4283     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4284
4285     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4286
4287     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4288         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4289
4290     stream->ra_entries[i].ts = time;
4291     stream->ra_entries[i].moof_offset = moof_offset;
4292
4293     /* don't want to go through the entire file and read all moofs at startup */
4294 #if 0
4295     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4296     if (ret != GST_FLOW_OK)
4297       goto corrupt_file;
4298     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4299         moof_offset, stream);
4300     gst_buffer_unref (buf);
4301 #endif
4302   }
4303
4304   check_update_duration (qtdemux, time);
4305
4306   return TRUE;
4307
4308 /* ERRORS */
4309 unknown_trackid:
4310   {
4311     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4312     return FALSE;
4313   }
4314 corrupt_file:
4315   {
4316     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4317     return FALSE;
4318   }
4319 no_samples:
4320   {
4321     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4322     return FALSE;
4323   }
4324 }
4325
4326 static gboolean
4327 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4328 {
4329   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4330   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4331   GstBuffer *mfro = NULL, *mfra = NULL;
4332   GstFlowReturn flow;
4333   gboolean ret = FALSE;
4334   GNode *mfra_node, *tfra_node;
4335   guint64 mfra_offset = 0;
4336   guint32 fourcc, mfra_size;
4337   gint64 len;
4338
4339   /* query upstream size in bytes */
4340   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4341     goto size_query_failed;
4342
4343   /* mfro box should be at the very end of the file */
4344   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4345   if (flow != GST_FLOW_OK)
4346     goto exit;
4347
4348   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4349
4350   fourcc = QT_FOURCC (mfro_map.data + 4);
4351   if (fourcc != FOURCC_mfro)
4352     goto exit;
4353
4354   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4355   if (mfro_map.size < 16)
4356     goto invalid_mfro_size;
4357
4358   mfra_size = QT_UINT32 (mfro_map.data + 12);
4359   if (mfra_size >= len)
4360     goto invalid_mfra_size;
4361
4362   mfra_offset = len - mfra_size;
4363
4364   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4365       mfra_offset, mfra_size);
4366
4367   /* now get and parse mfra box */
4368   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4369   if (flow != GST_FLOW_OK)
4370     goto broken_file;
4371
4372   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4373
4374   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4375   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4376
4377   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4378
4379   while (tfra_node) {
4380     qtdemux_parse_tfra (qtdemux, tfra_node);
4381     /* iterate all siblings */
4382     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4383   }
4384   g_node_destroy (mfra_node);
4385
4386   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4387   ret = TRUE;
4388
4389 exit:
4390
4391   if (mfro) {
4392     if (mfro_map.memory != NULL)
4393       gst_buffer_unmap (mfro, &mfro_map);
4394     gst_buffer_unref (mfro);
4395   }
4396   if (mfra) {
4397     if (mfra_map.memory != NULL)
4398       gst_buffer_unmap (mfra, &mfra_map);
4399     gst_buffer_unref (mfra);
4400   }
4401   return ret;
4402
4403 /* ERRORS */
4404 size_query_failed:
4405   {
4406     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4407     goto exit;
4408   }
4409 invalid_mfro_size:
4410   {
4411     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4412     goto exit;
4413   }
4414 invalid_mfra_size:
4415   {
4416     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4417     goto exit;
4418   }
4419 broken_file:
4420   {
4421     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4422     goto exit;
4423   }
4424 }
4425
4426 static guint64
4427 add_offset (guint64 offset, guint64 advance)
4428 {
4429   /* Avoid 64-bit overflow by clamping */
4430   if (offset > G_MAXUINT64 - advance)
4431     return G_MAXUINT64;
4432   return offset + advance;
4433 }
4434
4435 static GstFlowReturn
4436 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4437 {
4438   guint64 length = 0;
4439   guint32 fourcc = 0;
4440   GstBuffer *buf = NULL;
4441   GstFlowReturn ret = GST_FLOW_OK;
4442   guint64 cur_offset = qtdemux->offset;
4443   GstMapInfo map;
4444
4445   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4446   if (G_UNLIKELY (ret != GST_FLOW_OK))
4447     goto beach;
4448   gst_buffer_map (buf, &map, GST_MAP_READ);
4449   if (G_LIKELY (map.size >= 8))
4450     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4451   gst_buffer_unmap (buf, &map);
4452   gst_buffer_unref (buf);
4453
4454   /* maybe we already got most we needed, so only consider this eof */
4455   if (G_UNLIKELY (length == 0)) {
4456     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4457         (_("Invalid atom size.")),
4458         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4459             GST_FOURCC_ARGS (fourcc)));
4460     ret = GST_FLOW_EOS;
4461     goto beach;
4462   }
4463
4464   switch (fourcc) {
4465     case FOURCC_moof:
4466       /* record for later parsing when needed */
4467       if (!qtdemux->moof_offset) {
4468         qtdemux->moof_offset = qtdemux->offset;
4469       }
4470       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4471         /* FIXME */
4472       } else {
4473         qtdemux->offset += length;      /* skip moof and keep going */
4474       }
4475       if (qtdemux->got_moov) {
4476         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4477         ret = GST_FLOW_EOS;
4478         goto beach;
4479       }
4480       break;
4481     case FOURCC_mdat:
4482     case FOURCC_free:
4483     case FOURCC_skip:
4484     case FOURCC_wide:
4485     case FOURCC_PICT:
4486     case FOURCC_pnot:
4487     {
4488       GST_LOG_OBJECT (qtdemux,
4489           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4490           GST_FOURCC_ARGS (fourcc), cur_offset);
4491       qtdemux->offset = add_offset (qtdemux->offset, length);
4492       break;
4493     }
4494     case FOURCC_moov:
4495     {
4496       GstBuffer *moov = NULL;
4497
4498       if (qtdemux->got_moov) {
4499         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4500         qtdemux->offset = add_offset (qtdemux->offset, length);
4501         goto beach;
4502       }
4503
4504       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4505       if (ret != GST_FLOW_OK)
4506         goto beach;
4507       gst_buffer_map (moov, &map, GST_MAP_READ);
4508
4509       if (length != map.size) {
4510         /* Some files have a 'moov' atom at the end of the file which contains
4511          * a terminal 'free' atom where the body of the atom is missing.
4512          * Check for, and permit, this special case.
4513          */
4514         if (map.size >= 8) {
4515           guint8 *final_data = map.data + (map.size - 8);
4516           guint32 final_length = QT_UINT32 (final_data);
4517           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4518
4519           if (final_fourcc == FOURCC_free
4520               && map.size + final_length - 8 == length) {
4521             /* Ok, we've found that special case. Allocate a new buffer with
4522              * that free atom actually present. */
4523             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4524             gst_buffer_fill (newmoov, 0, map.data, map.size);
4525             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4526             gst_buffer_unmap (moov, &map);
4527             gst_buffer_unref (moov);
4528             moov = newmoov;
4529             gst_buffer_map (moov, &map, GST_MAP_READ);
4530           }
4531         }
4532       }
4533
4534       if (length != map.size) {
4535         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4536             (_("This file is incomplete and cannot be played.")),
4537             ("We got less than expected (received %" G_GSIZE_FORMAT
4538                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4539                 (guint) length, cur_offset));
4540         gst_buffer_unmap (moov, &map);
4541         gst_buffer_unref (moov);
4542         ret = GST_FLOW_ERROR;
4543         goto beach;
4544       }
4545       qtdemux->offset += length;
4546
4547       qtdemux_parse_moov (qtdemux, map.data, length);
4548       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4549
4550       qtdemux_parse_tree (qtdemux);
4551       if (qtdemux->moov_node_compressed) {
4552         g_node_destroy (qtdemux->moov_node_compressed);
4553         g_free (qtdemux->moov_node->data);
4554       }
4555       qtdemux->moov_node_compressed = NULL;
4556       g_node_destroy (qtdemux->moov_node);
4557       qtdemux->moov_node = NULL;
4558       gst_buffer_unmap (moov, &map);
4559       gst_buffer_unref (moov);
4560       qtdemux->got_moov = TRUE;
4561
4562       break;
4563     }
4564     case FOURCC_ftyp:
4565     {
4566       GstBuffer *ftyp = NULL;
4567
4568       /* extract major brand; might come in handy for ISO vs QT issues */
4569       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4570       if (ret != GST_FLOW_OK)
4571         goto beach;
4572       qtdemux->offset += length;
4573       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4574       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4575       gst_buffer_unmap (ftyp, &map);
4576       gst_buffer_unref (ftyp);
4577       break;
4578     }
4579     case FOURCC_uuid:
4580     {
4581       GstBuffer *uuid = NULL;
4582
4583       /* uuid are extension atoms */
4584       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4585       if (ret != GST_FLOW_OK)
4586         goto beach;
4587       qtdemux->offset += length;
4588       gst_buffer_map (uuid, &map, GST_MAP_READ);
4589       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4590       gst_buffer_unmap (uuid, &map);
4591       gst_buffer_unref (uuid);
4592       break;
4593     }
4594     case FOURCC_sidx:
4595     {
4596       GstBuffer *sidx = NULL;
4597       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4598       if (ret != GST_FLOW_OK)
4599         goto beach;
4600       qtdemux->offset += length;
4601       gst_buffer_map (sidx, &map, GST_MAP_READ);
4602       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4603       gst_buffer_unmap (sidx, &map);
4604       gst_buffer_unref (sidx);
4605       break;
4606     }
4607     default:
4608     {
4609       GstBuffer *unknown = NULL;
4610
4611       GST_LOG_OBJECT (qtdemux,
4612           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4613           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4614           cur_offset);
4615       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4616       if (ret != GST_FLOW_OK)
4617         goto beach;
4618       gst_buffer_map (unknown, &map, GST_MAP_READ);
4619       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4620       gst_buffer_unmap (unknown, &map);
4621       gst_buffer_unref (unknown);
4622       qtdemux->offset += length;
4623       break;
4624     }
4625   }
4626
4627 beach:
4628   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4629     /* digested all data, show what we have */
4630     qtdemux_prepare_streams (qtdemux);
4631     QTDEMUX_EXPOSE_LOCK (qtdemux);
4632     ret = qtdemux_expose_streams (qtdemux);
4633     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4634
4635     qtdemux->state = QTDEMUX_STATE_MOVIE;
4636     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4637         qtdemux->state);
4638     return ret;
4639   }
4640   return ret;
4641 }
4642
4643 /* Seeks to the previous keyframe of the indexed stream and
4644  * aligns other streams with respect to the keyframe timestamp
4645  * of indexed stream. Only called in case of Reverse Playback
4646  */
4647 static GstFlowReturn
4648 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4649 {
4650   guint32 seg_idx = 0, k_index = 0;
4651   guint32 ref_seg_idx, ref_k_index;
4652   GstClockTime k_pos = 0, last_stop = 0;
4653   QtDemuxSegment *seg = NULL;
4654   QtDemuxStream *ref_str = NULL;
4655   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4656   guint64 target_ts;
4657   gint i;
4658
4659   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4660    * and finally align all the other streams on that timestamp with their
4661    * respective keyframes */
4662   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4663     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4664
4665     /* No candidate yet, take the first stream */
4666     if (!ref_str) {
4667       ref_str = str;
4668       continue;
4669     }
4670
4671     /* So that stream has a segment, we prefer video streams */
4672     if (str->subtype == FOURCC_vide) {
4673       ref_str = str;
4674       break;
4675     }
4676   }
4677
4678   if (G_UNLIKELY (!ref_str)) {
4679     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4680     goto eos;
4681   }
4682
4683   if (G_UNLIKELY (!ref_str->from_sample)) {
4684     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4685     goto eos;
4686   }
4687
4688   /* So that stream has been playing from from_sample to to_sample. We will
4689    * get the timestamp of the previous sample and search for a keyframe before
4690    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4691   if (ref_str->subtype == FOURCC_vide) {
4692     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4693         ref_str->from_sample - 1, FALSE);
4694   } else {
4695     if (ref_str->from_sample >= 10)
4696       k_index = ref_str->from_sample - 10;
4697     else
4698       k_index = 0;
4699   }
4700
4701   target_ts =
4702       ref_str->samples[k_index].timestamp +
4703       ref_str->samples[k_index].pts_offset;
4704
4705   /* get current segment for that stream */
4706   seg = &ref_str->segments[ref_str->segment_index];
4707   /* Use segment start in original timescale for comparisons */
4708   seg_media_start_mov = seg->trak_media_start;
4709
4710   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4711       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4712       k_index, target_ts, seg_media_start_mov,
4713       GST_TIME_ARGS (seg->media_start));
4714
4715   /* Crawl back through segments to find the one containing this I frame */
4716   while (target_ts < seg_media_start_mov) {
4717     GST_DEBUG_OBJECT (qtdemux,
4718         "keyframe position (sample %u) is out of segment %u " " target %"
4719         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4720         ref_str->segment_index, target_ts, seg_media_start_mov);
4721
4722     if (G_UNLIKELY (!ref_str->segment_index)) {
4723       /* Reached first segment, let's consider it's EOS */
4724       goto eos;
4725     }
4726     ref_str->segment_index--;
4727     seg = &ref_str->segments[ref_str->segment_index];
4728     /* Use segment start in original timescale for comparisons */
4729     seg_media_start_mov = seg->trak_media_start;
4730   }
4731   /* Calculate time position of the keyframe and where we should stop */
4732   k_pos =
4733       QTSTREAMTIME_TO_GSTTIME (ref_str,
4734       target_ts - seg->trak_media_start) + seg->time;
4735   last_stop =
4736       QTSTREAMTIME_TO_GSTTIME (ref_str,
4737       ref_str->samples[ref_str->from_sample].timestamp -
4738       seg->trak_media_start) + seg->time;
4739
4740   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4741       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4742       k_index, GST_TIME_ARGS (k_pos));
4743
4744   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4745   qtdemux->segment.position = last_stop;
4746   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4747       GST_TIME_ARGS (last_stop));
4748
4749   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4750     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4751     goto eos;
4752   }
4753
4754   ref_seg_idx = ref_str->segment_index;
4755   ref_k_index = k_index;
4756
4757   /* Align them all on this */
4758   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4759     guint32 index = 0;
4760     GstClockTime seg_time = 0;
4761     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4762
4763     /* aligning reference stream again might lead to backing up to yet another
4764      * keyframe (due to timestamp rounding issues),
4765      * potentially putting more load on downstream; so let's try to avoid */
4766     if (str == ref_str) {
4767       seg_idx = ref_seg_idx;
4768       seg = &str->segments[seg_idx];
4769       k_index = ref_k_index;
4770       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4771           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4772     } else {
4773       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4774       GST_DEBUG_OBJECT (qtdemux,
4775           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4776           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4777
4778       /* get segment and time in the segment */
4779       seg = &str->segments[seg_idx];
4780       seg_time = k_pos - seg->time;
4781
4782       /* get the media time in the segment.
4783        * No adjustment for empty "filler" segments */
4784       if (seg->media_start != GST_CLOCK_TIME_NONE)
4785         seg_time += seg->media_start;
4786
4787       /* get the index of the sample with media time */
4788       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4789       GST_DEBUG_OBJECT (qtdemux,
4790           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4791           GST_TIME_ARGS (seg_time), index);
4792
4793       /* find previous keyframe */
4794       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4795     }
4796
4797     /* Remember until where we want to go */
4798     str->to_sample = str->from_sample - 1;
4799     /* Define our time position */
4800     target_ts =
4801         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4802     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4803     if (seg->media_start != GST_CLOCK_TIME_NONE)
4804       str->time_position -= seg->media_start;
4805
4806     /* Now seek back in time */
4807     gst_qtdemux_move_stream (qtdemux, str, k_index);
4808     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4809         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4810         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4811   }
4812
4813   return GST_FLOW_OK;
4814
4815 eos:
4816   return GST_FLOW_EOS;
4817 }
4818
4819 /*
4820  * Gets the current qt segment start, stop and position for the
4821  * given time offset. This is used in update_segment()
4822  */
4823 static void
4824 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4825     QtDemuxStream * stream, GstClockTime offset,
4826     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4827 {
4828   GstClockTime seg_time;
4829   GstClockTime start, stop, time;
4830   QtDemuxSegment *segment;
4831
4832   segment = &stream->segments[stream->segment_index];
4833
4834   /* get time in this segment */
4835   seg_time = (offset - segment->time) * segment->rate;
4836
4837   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4838       GST_TIME_ARGS (seg_time));
4839
4840   if (G_UNLIKELY (seg_time > segment->duration)) {
4841     GST_LOG_OBJECT (stream->pad,
4842         "seg_time > segment->duration %" GST_TIME_FORMAT,
4843         GST_TIME_ARGS (segment->duration));
4844     seg_time = segment->duration;
4845   }
4846
4847   /* qtdemux->segment.stop is in outside-time-realm, whereas
4848    * segment->media_stop is in track-time-realm.
4849    *
4850    * In order to compare the two, we need to bring segment.stop
4851    * into the track-time-realm
4852    *
4853    * FIXME - does this comment still hold? Don't see any conversion here */
4854
4855   stop = qtdemux->segment.stop;
4856   if (stop == GST_CLOCK_TIME_NONE)
4857     stop = qtdemux->segment.duration;
4858   if (stop == GST_CLOCK_TIME_NONE)
4859     stop = segment->media_stop;
4860   else
4861     stop =
4862         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4863
4864   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4865     start = segment->time + seg_time;
4866     time = offset;
4867     stop = start - seg_time + segment->duration;
4868   } else if (qtdemux->segment.rate >= 0) {
4869     start = MIN (segment->media_start + seg_time, stop);
4870     time = offset;
4871   } else {
4872     if (segment->media_start >= qtdemux->segment.start) {
4873       time = segment->time;
4874     } else {
4875       time = segment->time + (qtdemux->segment.start - segment->media_start);
4876     }
4877
4878     start = MAX (segment->media_start, qtdemux->segment.start);
4879     stop = MIN (segment->media_start + seg_time, stop);
4880   }
4881
4882   *_start = start;
4883   *_stop = stop;
4884   *_time = time;
4885 }
4886
4887 /*
4888  * Updates the qt segment used for the stream and pushes a new segment event
4889  * downstream on this stream's pad.
4890  */
4891 static gboolean
4892 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4893     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4894     GstClockTime * _stop)
4895 {
4896   QtDemuxSegment *segment;
4897   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4898   gdouble rate;
4899   GstEvent *event;
4900
4901   /* update the current segment */
4902   stream->segment_index = seg_idx;
4903
4904   /* get the segment */
4905   segment = &stream->segments[seg_idx];
4906
4907   if (G_UNLIKELY (offset < segment->time)) {
4908     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4909         GST_TIME_ARGS (segment->time));
4910     return FALSE;
4911   }
4912
4913   /* segment lies beyond total indicated duration */
4914   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4915           segment->time > qtdemux->segment.duration)) {
4916     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4917         " < segment->time %" GST_TIME_FORMAT,
4918         GST_TIME_ARGS (qtdemux->segment.duration),
4919         GST_TIME_ARGS (segment->time));
4920     return FALSE;
4921   }
4922
4923   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4924       &start, &stop, &time);
4925
4926   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4927       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4928       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4929
4930   /* combine global rate with that of the segment */
4931   rate = segment->rate * qtdemux->segment.rate;
4932
4933   /* Copy flags from main segment */
4934   stream->segment.flags = qtdemux->segment.flags;
4935
4936   /* update the segment values used for clipping */
4937   stream->segment.offset = qtdemux->segment.offset;
4938   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4939   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4940   stream->segment.rate = rate;
4941   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4942       stream->cslg_shift);
4943   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4944       stream->cslg_shift);
4945   stream->segment.time = time;
4946   stream->segment.position = stream->segment.start;
4947
4948   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4949       &stream->segment);
4950
4951   /* now prepare and send the segment */
4952   if (stream->pad) {
4953     event = gst_event_new_segment (&stream->segment);
4954     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4955       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4956     }
4957     gst_pad_push_event (stream->pad, event);
4958     /* assume we can send more data now */
4959     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4960     /* clear to send tags on this pad now */
4961     gst_qtdemux_push_tags (qtdemux, stream);
4962   }
4963
4964   if (_start)
4965     *_start = start;
4966   if (_stop)
4967     *_stop = stop;
4968
4969   return TRUE;
4970 }
4971
4972 /* activate the given segment number @seg_idx of @stream at time @offset.
4973  * @offset is an absolute global position over all the segments.
4974  *
4975  * This will push out a NEWSEGMENT event with the right values and
4976  * position the stream index to the first decodable sample before
4977  * @offset.
4978  */
4979 static gboolean
4980 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4981     guint32 seg_idx, GstClockTime offset)
4982 {
4983   QtDemuxSegment *segment;
4984   guint32 index, kf_index;
4985   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4986
4987   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4988       seg_idx, GST_TIME_ARGS (offset));
4989
4990   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4991           &start, &stop))
4992     return FALSE;
4993
4994   segment = &stream->segments[stream->segment_index];
4995
4996   /* in the fragmented case, we pick a fragment that starts before our
4997    * desired position and rely on downstream to wait for a keyframe
4998    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4999    * tfra entries tells us which trun/sample the key unit is in, but we don't
5000    * make use of this additional information at the moment) */
5001   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5002     stream->to_sample = G_MAXUINT32;
5003     return TRUE;
5004   } else {
5005     /* well, it will be taken care of below */
5006     qtdemux->fragmented_seek_pending = FALSE;
5007     /* FIXME ideally the do_fragmented_seek can be done right here,
5008      * rather than at loop level
5009      * (which might even allow handling edit lists in a fragmented file) */
5010   }
5011
5012   /* We don't need to look for a sample in push-based */
5013   if (!qtdemux->pullbased)
5014     return TRUE;
5015
5016   /* and move to the keyframe before the indicated media time of the
5017    * segment */
5018   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5019     if (qtdemux->segment.rate >= 0) {
5020       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5021       stream->to_sample = G_MAXUINT32;
5022       GST_DEBUG_OBJECT (stream->pad,
5023           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5024           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5025           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5026     } else {
5027       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5028       stream->to_sample = index;
5029       GST_DEBUG_OBJECT (stream->pad,
5030           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5031           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5032           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5033     }
5034   } else {
5035     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5036         "this is an empty segment");
5037     return TRUE;
5038   }
5039
5040   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5041    * encountered an error and printed a message so we return appropriately */
5042   if (index == -1)
5043     return FALSE;
5044
5045   /* we're at the right spot */
5046   if (index == stream->sample_index) {
5047     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5048     return TRUE;
5049   }
5050
5051   /* find keyframe of the target index */
5052   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5053
5054   /* go back two frames to provide lead-in for non-raw audio decoders */
5055   if (stream->subtype == FOURCC_soun && !stream->need_clip) {
5056     guint32 lead_in = 2;
5057     guint32 old_index = kf_index;
5058     GstStructure *s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
5059
5060     if (gst_structure_has_name (s, "audio/mpeg")) {
5061       gint mpegversion;
5062       if (gst_structure_get_int (s, "mpegversion", &mpegversion)
5063           && mpegversion == 1) {
5064         /* mp3 could need up to 30 frames of lead-in per mpegaudioparse */
5065         lead_in = 30;
5066       }
5067     }
5068
5069     kf_index = MAX (kf_index, lead_in) - lead_in;
5070     if (qtdemux_parse_samples (qtdemux, stream, kf_index)) {
5071       GST_DEBUG_OBJECT (stream->pad,
5072           "Moving backwards %u frames to ensure sufficient sound lead-in",
5073           old_index - kf_index);
5074     } else {
5075       kf_index = old_index;
5076     }
5077   }
5078
5079   /* if we move forwards, we don't have to go back to the previous
5080    * keyframe since we already sent that. We can also just jump to
5081    * the keyframe right before the target index if there is one. */
5082   if (index > stream->sample_index) {
5083     /* moving forwards check if we move past a keyframe */
5084     if (kf_index > stream->sample_index) {
5085       GST_DEBUG_OBJECT (stream->pad,
5086           "moving forwards to keyframe at %u "
5087           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5088           kf_index,
5089           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5090           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5091       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5092     } else {
5093       GST_DEBUG_OBJECT (stream->pad,
5094           "moving forwards, keyframe at %u "
5095           "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " ) already sent",
5096           kf_index,
5097           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5098           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5099     }
5100   } else {
5101     GST_DEBUG_OBJECT (stream->pad,
5102         "moving backwards to %sframe at %u "
5103         "(pts %" GST_TIME_FORMAT " dts %" GST_TIME_FORMAT " )",
5104         (stream->subtype == FOURCC_soun) ? "audio " : "key", kf_index,
5105         GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5106         GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5107     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5108   }
5109
5110   return TRUE;
5111 }
5112
5113 /* prepare to get the current sample of @stream, getting essential values.
5114  *
5115  * This function will also prepare and send the segment when needed.
5116  *
5117  * Return FALSE if the stream is EOS.
5118  *
5119  * PULL-BASED
5120  */
5121 static gboolean
5122 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5123     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5124     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5125     gboolean * keyframe)
5126 {
5127   QtDemuxSample *sample;
5128   GstClockTime time_position;
5129   guint32 seg_idx;
5130
5131   g_return_val_if_fail (stream != NULL, FALSE);
5132
5133   time_position = stream->time_position;
5134   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5135     goto eos;
5136
5137   seg_idx = stream->segment_index;
5138   if (G_UNLIKELY (seg_idx == -1)) {
5139     /* find segment corresponding to time_position if we are looking
5140      * for a segment. */
5141     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5142   }
5143
5144   /* different segment, activate it, sample_index will be set. */
5145   if (G_UNLIKELY (stream->segment_index != seg_idx))
5146     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5147
5148   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5149               segments[stream->segment_index]))) {
5150     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5151
5152     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5153         " prepare empty sample");
5154
5155     *empty = TRUE;
5156     *pts = *dts = time_position;
5157     *duration = seg->duration - (time_position - seg->time);
5158
5159     return TRUE;
5160   }
5161
5162   *empty = FALSE;
5163
5164   if (stream->sample_index == -1)
5165     stream->sample_index = 0;
5166
5167   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5168       stream->sample_index, stream->n_samples);
5169
5170   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5171     if (!qtdemux->fragmented)
5172       goto eos;
5173
5174     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5175     do {
5176       GstFlowReturn flow;
5177
5178       GST_OBJECT_LOCK (qtdemux);
5179       flow = qtdemux_add_fragmented_samples (qtdemux);
5180       GST_OBJECT_UNLOCK (qtdemux);
5181
5182       if (flow != GST_FLOW_OK)
5183         goto eos;
5184     }
5185     while (stream->sample_index >= stream->n_samples);
5186   }
5187
5188   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5189     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5190         stream->sample_index);
5191     return FALSE;
5192   }
5193
5194   /* now get the info for the sample we're at */
5195   sample = &stream->samples[stream->sample_index];
5196
5197   *dts = QTSAMPLE_DTS (stream, sample);
5198   *pts = QTSAMPLE_PTS (stream, sample);
5199   *offset = sample->offset;
5200   *size = sample->size;
5201   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5202   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5203
5204   return TRUE;
5205
5206   /* special cases */
5207 eos:
5208   {
5209     stream->time_position = GST_CLOCK_TIME_NONE;
5210     return FALSE;
5211   }
5212 }
5213
5214 /* move to the next sample in @stream.
5215  *
5216  * Moves to the next segment when needed.
5217  */
5218 static void
5219 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5220 {
5221   QtDemuxSample *sample;
5222   QtDemuxSegment *segment;
5223
5224   /* get current segment */
5225   segment = &stream->segments[stream->segment_index];
5226
5227   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5228     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5229     goto next_segment;
5230   }
5231
5232   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5233     /* Mark the stream as EOS */
5234     GST_DEBUG_OBJECT (qtdemux,
5235         "reached max allowed sample %u, mark EOS", stream->to_sample);
5236     stream->time_position = GST_CLOCK_TIME_NONE;
5237     return;
5238   }
5239
5240   /* move to next sample */
5241   stream->sample_index++;
5242   stream->offset_in_sample = 0;
5243
5244   GST_TRACE_OBJECT (qtdemux, "advance to sample %u/%u", stream->sample_index,
5245       stream->n_samples);
5246
5247   /* reached the last sample, we need the next segment */
5248   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5249     goto next_segment;
5250
5251   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5252     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5253         stream->sample_index);
5254     return;
5255   }
5256
5257   /* get next sample */
5258   sample = &stream->samples[stream->sample_index];
5259
5260   GST_TRACE_OBJECT (qtdemux, "sample dts %" GST_TIME_FORMAT " media_stop: %"
5261       GST_TIME_FORMAT, GST_TIME_ARGS (QTSAMPLE_DTS (stream, sample)),
5262       GST_TIME_ARGS (segment->media_stop));
5263
5264   /* see if we are past the segment */
5265   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5266     goto next_segment;
5267
5268   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5269     /* inside the segment, update time_position, looks very familiar to
5270      * GStreamer segments, doesn't it? */
5271     stream->time_position =
5272         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5273   } else {
5274     /* not yet in segment, time does not yet increment. This means
5275      * that we are still prerolling keyframes to the decoder so it can
5276      * decode the first sample of the segment. */
5277     stream->time_position = segment->time;
5278   }
5279   return;
5280
5281   /* move to the next segment */
5282 next_segment:
5283   {
5284     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5285
5286     if (stream->segment_index == stream->n_segments - 1) {
5287       /* are we at the end of the last segment, we're EOS */
5288       stream->time_position = GST_CLOCK_TIME_NONE;
5289     } else {
5290       /* else we're only at the end of the current segment */
5291       stream->time_position = segment->stop_time;
5292     }
5293     /* make sure we select a new segment */
5294
5295     /* accumulate previous segments */
5296     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5297       stream->accumulated_base +=
5298           (stream->segment.stop -
5299           stream->segment.start) / ABS (stream->segment.rate);
5300
5301     stream->segment_index = -1;
5302   }
5303 }
5304
5305 static void
5306 gst_qtdemux_sync_streams (GstQTDemux * demux)
5307 {
5308   gint i;
5309
5310   if (QTDEMUX_N_STREAMS (demux) <= 1)
5311     return;
5312
5313   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5314     QtDemuxStream *stream;
5315     GstClockTime end_time;
5316
5317     stream = QTDEMUX_NTH_STREAM (demux, i);
5318
5319     if (!stream->pad)
5320       continue;
5321
5322     /* TODO advance time on subtitle streams here, if any some day */
5323
5324     /* some clips/trailers may have unbalanced streams at the end,
5325      * so send EOS on shorter stream to prevent stalling others */
5326
5327     /* do not mess with EOS if SEGMENT seeking */
5328     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5329       continue;
5330
5331     if (demux->pullbased) {
5332       /* loop mode is sample time based */
5333       if (!STREAM_IS_EOS (stream))
5334         continue;
5335     } else {
5336       /* push mode is byte position based */
5337       if (stream->n_samples &&
5338           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5339         continue;
5340     }
5341
5342     if (stream->sent_eos)
5343       continue;
5344
5345     /* only act if some gap */
5346     end_time = stream->segments[stream->n_segments - 1].stop_time;
5347     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5348         ", stream end: %" GST_TIME_FORMAT,
5349         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5350     if (GST_CLOCK_TIME_IS_VALID (end_time)
5351         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5352       GstEvent *event;
5353
5354       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5355           GST_PAD_NAME (stream->pad));
5356       stream->sent_eos = TRUE;
5357       event = gst_event_new_eos ();
5358       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5359         gst_event_set_seqnum (event, demux->segment_seqnum);
5360       gst_pad_push_event (stream->pad, event);
5361     }
5362   }
5363 }
5364
5365 /* EOS and NOT_LINKED need to be combined. This means that we return:
5366  *
5367  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5368  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5369  */
5370 static GstFlowReturn
5371 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5372     GstFlowReturn ret)
5373 {
5374   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5375
5376   if (stream->pad)
5377     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5378         ret);
5379   else
5380     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5381
5382   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5383   return ret;
5384 }
5385
5386 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5387  * completely clipped
5388  *
5389  * Should be used only with raw buffers */
5390 static GstBuffer *
5391 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5392     GstBuffer * buf)
5393 {
5394   guint64 start, stop, cstart, cstop, diff;
5395   GstClockTime pts, duration;
5396   gsize size, osize;
5397   gint num_rate, denom_rate;
5398   gint frame_size;
5399   gboolean clip_data;
5400   guint offset;
5401
5402   osize = size = gst_buffer_get_size (buf);
5403   offset = 0;
5404
5405   /* depending on the type, setup the clip parameters */
5406   if (stream->subtype == FOURCC_soun) {
5407     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5408     num_rate = GST_SECOND;
5409     denom_rate = (gint) CUR_STREAM (stream)->rate;
5410     clip_data = TRUE;
5411   } else if (stream->subtype == FOURCC_vide) {
5412     frame_size = size;
5413     num_rate = CUR_STREAM (stream)->fps_n;
5414     denom_rate = CUR_STREAM (stream)->fps_d;
5415     clip_data = FALSE;
5416   } else
5417     goto wrong_type;
5418
5419   if (frame_size <= 0)
5420     goto bad_frame_size;
5421
5422   /* we can only clip if we have a valid pts */
5423   pts = GST_BUFFER_PTS (buf);
5424   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5425     goto no_pts;
5426
5427   duration = GST_BUFFER_DURATION (buf);
5428
5429   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5430     duration =
5431         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5432   }
5433
5434   start = pts;
5435   stop = start + duration;
5436
5437   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5438               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5439     goto clipped;
5440
5441   /* see if some clipping happened */
5442   diff = cstart - start;
5443   if (diff > 0) {
5444     pts += diff;
5445     duration -= diff;
5446
5447     if (clip_data) {
5448       /* bring clipped time to samples and to bytes */
5449       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5450       diff *= frame_size;
5451
5452       GST_DEBUG_OBJECT (qtdemux,
5453           "clipping start to %" GST_TIME_FORMAT " %"
5454           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5455
5456       offset = diff;
5457       size -= diff;
5458     }
5459   }
5460   diff = stop - cstop;
5461   if (diff > 0) {
5462     duration -= diff;
5463
5464     if (clip_data) {
5465       /* bring clipped time to samples and then to bytes */
5466       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5467       diff *= frame_size;
5468       GST_DEBUG_OBJECT (qtdemux,
5469           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5470           " bytes", GST_TIME_ARGS (cstop), diff);
5471       size -= diff;
5472     }
5473   }
5474
5475   if (offset != 0 || size != osize)
5476     gst_buffer_resize (buf, offset, size);
5477
5478   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5479   GST_BUFFER_PTS (buf) = pts;
5480   GST_BUFFER_DURATION (buf) = duration;
5481
5482   return buf;
5483
5484   /* dropped buffer */
5485 wrong_type:
5486   {
5487     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5488     return buf;
5489   }
5490 bad_frame_size:
5491   {
5492     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5493     return buf;
5494   }
5495 no_pts:
5496   {
5497     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5498     return buf;
5499   }
5500 clipped:
5501   {
5502     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5503     gst_buffer_unref (buf);
5504     return NULL;
5505   }
5506 }
5507
5508 static GstBuffer *
5509 gst_qtdemux_align_buffer (GstQTDemux * demux,
5510     GstBuffer * buffer, gsize alignment)
5511 {
5512   GstMapInfo map;
5513
5514   gst_buffer_map (buffer, &map, GST_MAP_READ);
5515
5516   if (map.size < sizeof (guintptr)) {
5517     gst_buffer_unmap (buffer, &map);
5518     return buffer;
5519   }
5520
5521   if (((guintptr) map.data) & (alignment - 1)) {
5522     GstBuffer *new_buffer;
5523     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5524
5525     new_buffer = gst_buffer_new_allocate (NULL,
5526         gst_buffer_get_size (buffer), &params);
5527
5528     /* Copy data "by hand", so ensure alignment is kept: */
5529     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5530
5531     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5532     GST_DEBUG_OBJECT (demux,
5533         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5534         alignment);
5535
5536     gst_buffer_unmap (buffer, &map);
5537     gst_buffer_unref (buffer);
5538
5539     return new_buffer;
5540   }
5541
5542   gst_buffer_unmap (buffer, &map);
5543   return buffer;
5544 }
5545
5546 static guint8 *
5547 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5548     gsize * res)
5549 {
5550   guint8 *storage;
5551   gsize i;
5552
5553   /* We are converting from pairs to triplets */
5554   *res = ccpair_size / 2 * 3;
5555   storage = g_malloc (*res);
5556   for (i = 0; i * 2 < ccpair_size; i += 1) {
5557     /* FIXME: Use line offset 0 as we simply can't know here */
5558     if (field == 1)
5559       storage[i * 3] = 0x80 | 0x00;
5560     else
5561       storage[i * 3] = 0x00 | 0x00;
5562     storage[i * 3 + 1] = ccpair[i * 2];
5563     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5564   }
5565
5566   return storage;
5567 }
5568
5569 static guint8 *
5570 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5571     gsize * cclen)
5572 {
5573   guint8 *res = NULL;
5574   guint32 atom_length, fourcc;
5575   QtDemuxStreamStsdEntry *stsd_entry;
5576
5577   GST_MEMDUMP ("caption atom", data, size);
5578
5579   /* There might be multiple atoms */
5580
5581   *cclen = 0;
5582   if (size < 8)
5583     goto invalid_cdat;
5584   atom_length = QT_UINT32 (data);
5585   fourcc = QT_FOURCC (data + 4);
5586   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5587     goto invalid_cdat;
5588
5589   GST_DEBUG_OBJECT (stream->pad, "here");
5590
5591   /* Check if we have something compatible */
5592   stsd_entry = CUR_STREAM (stream);
5593   switch (stsd_entry->fourcc) {
5594     case FOURCC_c608:{
5595       guint8 *cdat = NULL, *cdt2 = NULL;
5596       gsize cdat_size = 0, cdt2_size = 0;
5597       /* Should be cdat or cdt2 */
5598       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5599         GST_WARNING_OBJECT (stream->pad,
5600             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5601             GST_FOURCC_ARGS (fourcc));
5602         goto invalid_cdat;
5603       }
5604
5605       /* Convert to S334-1 Annex A byte triplet */
5606       if (fourcc == FOURCC_cdat)
5607         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5608       else
5609         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5610       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5611           size, atom_length);
5612
5613       /* Check for another atom ? */
5614       if (size > atom_length + 8) {
5615         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5616         if (size >= atom_length + new_atom_length) {
5617           fourcc = QT_FOURCC (data + atom_length + 4);
5618           if (fourcc == FOURCC_cdat) {
5619             if (cdat == NULL)
5620               cdat =
5621                   convert_to_s334_1a (data + atom_length + 8,
5622                   new_atom_length - 8, 1, &cdat_size);
5623             else
5624               GST_WARNING_OBJECT (stream->pad,
5625                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5626           } else {
5627             if (cdt2 == NULL)
5628               cdt2 =
5629                   convert_to_s334_1a (data + atom_length + 8,
5630                   new_atom_length - 8, 2, &cdt2_size);
5631             else
5632               GST_WARNING_OBJECT (stream->pad,
5633                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5634           }
5635         }
5636       }
5637
5638       *cclen = cdat_size + cdt2_size;
5639       res = g_malloc (*cclen);
5640       if (cdat_size)
5641         memcpy (res, cdat, cdat_size);
5642       if (cdt2_size)
5643         memcpy (res + cdat_size, cdt2, cdt2_size);
5644       g_free (cdat);
5645       g_free (cdt2);
5646     }
5647       break;
5648     case FOURCC_c708:
5649       if (fourcc != FOURCC_ccdp) {
5650         GST_WARNING_OBJECT (stream->pad,
5651             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5652             GST_FOURCC_ARGS (fourcc));
5653         goto invalid_cdat;
5654       }
5655       *cclen = atom_length - 8;
5656       res = g_memdup2 (data + 8, *cclen);
5657       break;
5658     default:
5659       /* Keep this here in case other closed caption formats are added */
5660       g_assert_not_reached ();
5661       break;
5662   }
5663
5664   GST_MEMDUMP ("Output", res, *cclen);
5665   return res;
5666
5667   /* Errors */
5668 invalid_cdat:
5669   GST_WARNING ("[cdat] atom is too small or invalid");
5670   return NULL;
5671 }
5672
5673 /* Handle Closed Caption sample buffers.
5674  * The input buffer metadata must be writable,
5675  * but time/duration etc not yet set and need not be preserved */
5676 static GstBuffer *
5677 gst_qtdemux_process_buffer_clcp (GstQTDemux * qtdemux, QtDemuxStream * stream,
5678     GstBuffer * buf)
5679 {
5680   GstBuffer *outbuf = NULL;
5681   GstMapInfo map;
5682   guint8 *cc;
5683   gsize cclen = 0;
5684
5685   gst_buffer_map (buf, &map, GST_MAP_READ);
5686
5687   /* empty buffer is sent to terminate previous subtitle */
5688   if (map.size <= 2) {
5689     gst_buffer_unmap (buf, &map);
5690     gst_buffer_unref (buf);
5691     return NULL;
5692   }
5693
5694   /* For closed caption, we need to extract the information from the
5695    * [cdat],[cdt2] or [ccdp] atom */
5696   cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5697   gst_buffer_unmap (buf, &map);
5698   if (cc) {
5699     outbuf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5700     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5701   } else {
5702     /* Conversion failed or there's nothing */
5703   }
5704   gst_buffer_unref (buf);
5705
5706   return outbuf;
5707 }
5708
5709 /* DVD subpicture specific sample handling.
5710  * the input buffer metadata must be writable,
5711  * but time/duration etc not yet set and need not be preserved */
5712 static GstBuffer *
5713 gst_qtdemux_process_buffer_dvd (GstQTDemux * qtdemux, QtDemuxStream * stream,
5714     GstBuffer * buf)
5715 {
5716   /* send a one time dvd clut event */
5717   if (stream->pending_event && stream->pad)
5718     gst_pad_push_event (stream->pad, stream->pending_event);
5719   stream->pending_event = NULL;
5720
5721   /* empty buffer is sent to terminate previous subtitle */
5722   if (gst_buffer_get_size (buf) <= 2) {
5723     gst_buffer_unref (buf);
5724     return NULL;
5725   }
5726
5727   /* That's all the processing needed for subpictures */
5728   return buf;
5729 }
5730
5731 /* Timed text formats
5732  * the input buffer metadata must be writable,
5733  * but time/duration etc not yet set and need not be preserved */
5734 static GstBuffer *
5735 gst_qtdemux_process_buffer_text (GstQTDemux * qtdemux, QtDemuxStream * stream,
5736     GstBuffer * buf)
5737 {
5738   GstBuffer *outbuf = NULL;
5739   GstMapInfo map;
5740   guint nsize = 0;
5741   gchar *str;
5742
5743   /* not many cases for now */
5744   if (G_UNLIKELY (stream->subtype != FOURCC_text &&
5745           stream->subtype != FOURCC_sbtl)) {
5746     return buf;
5747   }
5748
5749   gst_buffer_map (buf, &map, GST_MAP_READ);
5750
5751   /* empty buffer is sent to terminate previous subtitle */
5752   if (map.size <= 2) {
5753     gst_buffer_unmap (buf, &map);
5754     gst_buffer_unref (buf);
5755     return NULL;
5756   }
5757
5758   nsize = GST_READ_UINT16_BE (map.data);
5759   nsize = MIN (nsize, map.size - 2);
5760
5761   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5762       nsize, map.size);
5763
5764   /* takes care of UTF-8 validation or UTF-16 recognition,
5765    * no other encoding expected */
5766   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5767   gst_buffer_unmap (buf, &map);
5768
5769   if (str) {
5770     outbuf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5771     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5772   } else {
5773     /* this should not really happen unless the subtitle is corrupted */
5774   }
5775   gst_buffer_unref (buf);
5776
5777   /* FIXME ? convert optional subsequent style info to markup */
5778
5779   return outbuf;
5780 }
5781
5782 /* WebVTT sample handling according to 14496-30 */
5783 static GstBuffer *
5784 gst_qtdemux_process_buffer_wvtt (GstQTDemux * qtdemux, QtDemuxStream * stream,
5785     GstBuffer * buf)
5786 {
5787   GstBuffer *outbuf = NULL;
5788   GstMapInfo map;
5789
5790   if (!gst_buffer_map (buf, &map, GST_MAP_READ)) {
5791     g_assert_not_reached ();    /* The buffer must be mappable */
5792   }
5793
5794   if (qtdemux_webvtt_is_empty (qtdemux, map.data, map.size)) {
5795     GstEvent *gap = NULL;
5796     /* Push a gap event */
5797     stream->segment.position = GST_BUFFER_PTS (buf);
5798     gap =
5799         gst_event_new_gap (stream->segment.position, GST_BUFFER_DURATION (buf));
5800     gst_pad_push_event (stream->pad, gap);
5801
5802     if (GST_BUFFER_DURATION_IS_VALID (buf))
5803       stream->segment.position += GST_BUFFER_DURATION (buf);
5804   } else {
5805     outbuf =
5806         qtdemux_webvtt_decode (qtdemux, GST_BUFFER_PTS (buf),
5807         GST_BUFFER_DURATION (buf), map.data, map.size);
5808     gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
5809   }
5810
5811   gst_buffer_unmap (buf, &map);
5812   gst_buffer_unref (buf);
5813
5814   return outbuf;
5815 }
5816
5817 static GstFlowReturn
5818 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5819     GstBuffer * buf)
5820 {
5821   GstFlowReturn ret = GST_FLOW_OK;
5822   GstClockTime pts, duration;
5823
5824   if (stream->need_clip)
5825     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5826
5827   if (G_UNLIKELY (buf == NULL))
5828     goto exit;
5829
5830   if (G_UNLIKELY (stream->discont)) {
5831     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5832     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5833     stream->discont = FALSE;
5834   } else {
5835     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5836   }
5837
5838   GST_LOG_OBJECT (qtdemux,
5839       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5840       ", duration %" GST_TIME_FORMAT " on pad %s",
5841       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5842       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5843       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5844
5845   if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
5846     GstStructure *crypto_info;
5847     QtDemuxAavdEncryptionInfo *info =
5848         (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
5849
5850     crypto_info = gst_structure_copy (info->default_properties);
5851     if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5852       GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
5853   }
5854
5855   if (stream->protected && (stream->protection_scheme_type == FOURCC_cenc
5856           || stream->protection_scheme_type == FOURCC_cbcs)) {
5857     GstStructure *crypto_info;
5858     QtDemuxCencSampleSetInfo *info =
5859         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5860     gint index;
5861     GstEvent *event;
5862
5863     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5864       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5865           GST_PTR_FORMAT, event);
5866       gst_pad_push_event (stream->pad, event);
5867     }
5868
5869     if (info->crypto_info == NULL) {
5870       if (stream->protection_scheme_type == FOURCC_cbcs) {
5871         crypto_info = qtdemux_get_cenc_sample_properties (qtdemux, stream, 0);
5872         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info)) {
5873           GST_ERROR_OBJECT (qtdemux,
5874               "failed to attach cbcs metadata to buffer");
5875           qtdemux_gst_structure_free (crypto_info);
5876         } else {
5877           GST_TRACE_OBJECT (qtdemux, "added cbcs protection metadata");
5878         }
5879       } else {
5880         GST_DEBUG_OBJECT (qtdemux,
5881             "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5882       }
5883     } else {
5884       /* The end of the crypto_info array matches our n_samples position,
5885        * so count backward from there */
5886       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5887       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5888         /* steal structure from array */
5889         crypto_info = g_ptr_array_index (info->crypto_info, index);
5890         g_ptr_array_index (info->crypto_info, index) = NULL;
5891         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5892             info->crypto_info->len);
5893         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5894           GST_ERROR_OBJECT (qtdemux,
5895               "failed to attach cenc metadata to buffer");
5896       } else {
5897         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5898             index, stream->sample_index);
5899       }
5900     }
5901   }
5902
5903   if (stream->alignment > 1)
5904     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5905
5906   pts = GST_BUFFER_PTS (buf);
5907   duration = GST_BUFFER_DURATION (buf);
5908
5909   ret = gst_pad_push (stream->pad, buf);
5910
5911   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5912     /* mark position in stream, we'll need this to know when to send GAP event */
5913     stream->segment.position = pts + duration;
5914   }
5915
5916 exit:
5917
5918   return ret;
5919 }
5920
5921 static GstFlowReturn
5922 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5923     GstBuffer * buf)
5924 {
5925   GstFlowReturn ret = GST_FLOW_OK;
5926
5927   if (stream->subtype == FOURCC_clcp
5928       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5929     GstMapInfo map;
5930     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5931     guint n_triplets, i;
5932     guint field1_off = 0, field2_off = 0;
5933
5934     /* We have to split CEA608 buffers so that each outgoing buffer contains
5935      * one byte pair per field according to the framerate of the video track.
5936      *
5937      * If there is only a single byte pair per field we don't have to do
5938      * anything
5939      */
5940
5941     gst_buffer_map (buf, &map, GST_MAP_READ);
5942
5943     n_triplets = map.size / 3;
5944     for (i = 0; i < n_triplets; i++) {
5945       if (map.data[3 * i] & 0x80)
5946         n_field1++;
5947       else
5948         n_field2++;
5949     }
5950
5951     g_assert (n_field1 || n_field2);
5952
5953     /* If there's more than 1 frame we have to split, otherwise we can just
5954      * pass through */
5955     if (n_field1 > 1 || n_field2 > 1) {
5956       n_output_buffers =
5957           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5958           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5959
5960       for (i = 0; i < n_output_buffers; i++) {
5961         GstBuffer *outbuf =
5962             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5963         GstMapInfo outmap;
5964         guint8 *outptr;
5965
5966         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5967         outptr = outmap.data;
5968
5969         if (n_field1) {
5970           gboolean found = FALSE;
5971
5972           while (map.data + field1_off < map.data + map.size) {
5973             if (map.data[field1_off] & 0x80) {
5974               memcpy (outptr, &map.data[field1_off], 3);
5975               field1_off += 3;
5976               found = TRUE;
5977               break;
5978             }
5979             field1_off += 3;
5980           }
5981
5982           if (!found) {
5983             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5984
5985             memcpy (outptr, empty, 3);
5986           }
5987
5988           outptr += 3;
5989         }
5990
5991         if (n_field2) {
5992           gboolean found = FALSE;
5993
5994           while (map.data + field2_off < map.data + map.size) {
5995             if ((map.data[field2_off] & 0x80) == 0) {
5996               memcpy (outptr, &map.data[field2_off], 3);
5997               field2_off += 3;
5998               found = TRUE;
5999               break;
6000             }
6001             field2_off += 3;
6002           }
6003
6004           if (!found) {
6005             const guint8 empty[] = { 0x00, 0x80, 0x80 };
6006
6007             memcpy (outptr, empty, 3);
6008           }
6009
6010           outptr += 3;
6011         }
6012
6013         gst_buffer_unmap (outbuf, &outmap);
6014
6015         GST_BUFFER_PTS (outbuf) =
6016             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
6017             GST_SECOND * CUR_STREAM (stream)->fps_d,
6018             CUR_STREAM (stream)->fps_n);
6019         GST_BUFFER_DURATION (outbuf) =
6020             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
6021             CUR_STREAM (stream)->fps_n);
6022         GST_BUFFER_OFFSET (outbuf) = -1;
6023         GST_BUFFER_OFFSET_END (outbuf) = -1;
6024
6025         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6026
6027         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6028           break;
6029       }
6030       gst_buffer_unmap (buf, &map);
6031       gst_buffer_unref (buf);
6032     } else {
6033       gst_buffer_unmap (buf, &map);
6034       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6035     }
6036   } else {
6037     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6038   }
6039
6040   return ret;
6041 }
6042
6043 /* Sets a buffer's attributes properly and pushes it downstream.
6044  * Also checks for additional actions and custom processing that may
6045  * need to be done first.
6046  */
6047 static GstFlowReturn
6048 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6049     QtDemuxStream * stream, GstBuffer * buf,
6050     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6051     gboolean keyframe, GstClockTime position, guint64 byte_position)
6052 {
6053   GstFlowReturn ret = GST_FLOW_OK;
6054
6055   /* offset the timestamps according to the edit list */
6056
6057   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6058     gchar *url;
6059     GstMapInfo map;
6060
6061     gst_buffer_map (buf, &map, GST_MAP_READ);
6062     url = g_strndup ((gchar *) map.data, map.size);
6063     gst_buffer_unmap (buf, &map);
6064     if (url != NULL && strlen (url) != 0) {
6065       /* we have RTSP redirect now */
6066       g_free (qtdemux->redirect_location);
6067       qtdemux->redirect_location = g_strdup (url);
6068       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6069           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6070               gst_structure_new ("redirect",
6071                   "new-location", G_TYPE_STRING, url, NULL)));
6072     } else {
6073       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6074           "posting");
6075     }
6076     g_free (url);
6077   }
6078
6079   /* position reporting */
6080   if (qtdemux->segment.rate >= 0) {
6081     qtdemux->segment.position = position;
6082     gst_qtdemux_sync_streams (qtdemux);
6083   }
6084
6085   if (G_UNLIKELY (!stream->pad)) {
6086     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6087     gst_buffer_unref (buf);
6088     goto exit;
6089   }
6090
6091   /* send out pending buffers */
6092   while (stream->buffers) {
6093     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6094
6095     if (G_UNLIKELY (stream->discont)) {
6096       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6097       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6098       stream->discont = FALSE;
6099     } else {
6100       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6101     }
6102
6103     if (stream->alignment > 1)
6104       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6105     gst_pad_push (stream->pad, buffer);
6106
6107     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6108   }
6109
6110   /* we're going to modify the metadata */
6111   buf = gst_buffer_make_writable (buf);
6112
6113   GST_BUFFER_DTS (buf) = dts;
6114   GST_BUFFER_PTS (buf) = pts;
6115   GST_BUFFER_DURATION (buf) = duration;
6116   GST_BUFFER_OFFSET (buf) = -1;
6117   GST_BUFFER_OFFSET_END (buf) = -1;
6118
6119   if (G_UNLIKELY (stream->process_func))
6120     buf = stream->process_func (qtdemux, stream, buf);
6121
6122   if (!buf) {
6123     goto exit;
6124   }
6125
6126   if (!keyframe) {
6127     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6128     stream->on_keyframe = FALSE;
6129   } else {
6130     stream->on_keyframe = TRUE;
6131   }
6132
6133   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6134     gst_buffer_append_memory (buf,
6135         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6136
6137   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6138     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6139   }
6140 #if 0
6141   if (G_UNLIKELY (qtdemux->element_index)) {
6142     GstClockTime stream_time;
6143
6144     stream_time =
6145         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6146         timestamp);
6147     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6148       GST_LOG_OBJECT (qtdemux,
6149           "adding association %" GST_TIME_FORMAT "-> %"
6150           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6151       gst_index_add_association (qtdemux->element_index,
6152           qtdemux->index_id,
6153           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6154           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6155           GST_FORMAT_BYTES, byte_position, NULL);
6156     }
6157   }
6158 #endif
6159
6160   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6161
6162 exit:
6163   return ret;
6164 }
6165
6166 static const QtDemuxRandomAccessEntry *
6167 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6168     GstClockTime pos, gboolean after)
6169 {
6170   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6171   guint n_entries = stream->n_ra_entries;
6172   guint i;
6173
6174   /* we assume the table is sorted */
6175   for (i = 0; i < n_entries; ++i) {
6176     if (entries[i].ts > pos)
6177       break;
6178   }
6179
6180   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6181    * probably okay to assume that the index lists the very first fragment */
6182   if (i == 0)
6183     return &entries[0];
6184
6185   if (after)
6186     return &entries[i];
6187   else
6188     return &entries[i - 1];
6189 }
6190
6191 static gboolean
6192 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6193 {
6194   const QtDemuxRandomAccessEntry *best_entry = NULL;
6195   gint i;
6196
6197   GST_OBJECT_LOCK (qtdemux);
6198
6199   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6200
6201   /* first see if we can determine where to go to using mfra,
6202    * before we start clearing things */
6203   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6204     const QtDemuxRandomAccessEntry *entry;
6205     QtDemuxStream *stream;
6206     gboolean is_audio_or_video;
6207
6208     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6209
6210     if (stream->ra_entries == NULL)
6211       continue;
6212
6213     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6214       is_audio_or_video = TRUE;
6215     else
6216       is_audio_or_video = FALSE;
6217
6218     entry =
6219         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6220         stream->time_position, !is_audio_or_video);
6221
6222     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6223         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6224
6225     stream->pending_seek = entry;
6226
6227     /* decide position to jump to just based on audio/video tracks, not subs */
6228     if (!is_audio_or_video)
6229       continue;
6230
6231     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6232       best_entry = entry;
6233   }
6234
6235   /* no luck, will handle seek otherwise */
6236   if (best_entry == NULL) {
6237     GST_OBJECT_UNLOCK (qtdemux);
6238     return FALSE;
6239   }
6240
6241   /* ok, now we can prepare for processing as of located moof */
6242   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6243     QtDemuxStream *stream;
6244
6245     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6246
6247     g_free (stream->samples);
6248     stream->samples = NULL;
6249     stream->n_samples = 0;
6250     stream->stbl_index = -1;    /* no samples have yet been parsed */
6251     stream->sample_index = -1;
6252
6253     if (stream->protection_scheme_info) {
6254       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6255       if (stream->protection_scheme_type == FOURCC_cenc
6256           || stream->protection_scheme_type == FOURCC_cbcs) {
6257         QtDemuxCencSampleSetInfo *info =
6258             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6259         if (info->crypto_info) {
6260           g_ptr_array_free (info->crypto_info, TRUE);
6261           info->crypto_info = NULL;
6262         }
6263       }
6264     }
6265   }
6266
6267   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6268       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6269       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6270       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6271
6272   qtdemux->moof_offset = best_entry->moof_offset;
6273
6274   qtdemux_add_fragmented_samples (qtdemux);
6275
6276   GST_OBJECT_UNLOCK (qtdemux);
6277   return TRUE;
6278 }
6279
6280 static GstFlowReturn
6281 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6282 {
6283   GstFlowReturn ret = GST_FLOW_OK;
6284   GstBuffer *buf = NULL;
6285   QtDemuxStream *stream, *target_stream = NULL;
6286   GstClockTime min_time;
6287   guint64 offset = 0;
6288   GstClockTime dts = GST_CLOCK_TIME_NONE;
6289   GstClockTime pts = GST_CLOCK_TIME_NONE;
6290   GstClockTime duration = 0;
6291   gboolean keyframe = FALSE;
6292   guint sample_size = 0;
6293   guint num_samples = 1;
6294   gboolean empty = 0;
6295   guint size;
6296   gint i;
6297
6298   if (qtdemux->fragmented_seek_pending) {
6299     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6300     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6301       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6302       qtdemux->fragmented_seek_pending = FALSE;
6303     } else {
6304       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6305     }
6306   }
6307
6308   /* Figure out the next stream sample to output, min_time is expressed in
6309    * global time and runs over the edit list segments. */
6310   min_time = G_MAXUINT64;
6311   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6312     GstClockTime position;
6313
6314     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6315     position = stream->time_position;
6316
6317     if (!GST_CLOCK_TIME_IS_VALID (position))
6318       continue;
6319
6320     if (stream->segment_index != -1) {
6321       QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6322       position += segment->media_start;
6323     }
6324
6325     /* position of -1 is EOS */
6326     if (position < min_time) {
6327       min_time = position;
6328       target_stream = stream;
6329     }
6330   }
6331   /* all are EOS */
6332   if (G_UNLIKELY (target_stream == NULL)) {
6333     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6334     goto eos;
6335   }
6336
6337   /* check for segment end */
6338   if (G_UNLIKELY (qtdemux->segment.stop != -1
6339           && qtdemux->segment.rate >= 0
6340           && qtdemux->segment.stop <= min_time && target_stream->on_keyframe)) {
6341     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6342     target_stream->time_position = GST_CLOCK_TIME_NONE;
6343     goto eos_stream;
6344   }
6345
6346   /* gap events for subtitle streams */
6347   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6348     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6349     if (stream->pad) {
6350       GstClockTime gap_threshold;
6351
6352       /* Only send gap events on non-subtitle streams if lagging way behind. */
6353       if (stream->subtype == FOURCC_subp
6354           || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl ||
6355           stream->subtype == FOURCC_wvtt)
6356         gap_threshold = 1 * GST_SECOND;
6357       else
6358         gap_threshold = 3 * GST_SECOND;
6359
6360       /* send gap events until the stream catches up */
6361       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6362       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6363           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6364           stream->segment.position + gap_threshold < min_time) {
6365         GstEvent *gap =
6366             gst_event_new_gap (stream->segment.position, gap_threshold);
6367         gst_pad_push_event (stream->pad, gap);
6368         stream->segment.position += gap_threshold;
6369       }
6370     }
6371   }
6372
6373   stream = target_stream;
6374   /* fetch info for the current sample of this stream */
6375   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6376               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6377     goto eos_stream;
6378
6379   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6380   if (stream->new_caps) {
6381     gst_qtdemux_configure_stream (qtdemux, stream);
6382     qtdemux_do_allocation (stream, qtdemux);
6383   }
6384
6385   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6386   if (G_UNLIKELY (qtdemux->segment.
6387           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6388     if (stream->subtype == FOURCC_vide) {
6389       if (!keyframe) {
6390         GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6391             stream->track_id);
6392         goto next;
6393       } else if (qtdemux->trickmode_interval > 0) {
6394         GstClockTimeDiff interval;
6395
6396         if (qtdemux->segment.rate > 0)
6397           interval = stream->time_position - stream->last_keyframe_dts;
6398         else
6399           interval = stream->last_keyframe_dts - stream->time_position;
6400
6401         if (GST_CLOCK_TIME_IS_VALID (stream->last_keyframe_dts)
6402             && interval < qtdemux->trickmode_interval) {
6403           GST_LOG_OBJECT (qtdemux,
6404               "Skipping keyframe within interval on track-id %u",
6405               stream->track_id);
6406           goto next;
6407         } else {
6408           stream->last_keyframe_dts = stream->time_position;
6409         }
6410       }
6411     }
6412   }
6413
6414   GST_DEBUG_OBJECT (qtdemux,
6415       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6416       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6417       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6418       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6419       GST_TIME_ARGS (duration));
6420
6421   if (G_UNLIKELY (empty)) {
6422     /* empty segment, push a gap if there's a second or more
6423      * difference and move to the next one */
6424     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6425       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6426     stream->segment.position = pts + duration;
6427     goto next;
6428   }
6429
6430   /* hmm, empty sample, skip and move to next sample */
6431   if (G_UNLIKELY (sample_size <= 0))
6432     goto next;
6433
6434   /* last pushed sample was out of boundary, goto next sample */
6435   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6436     goto next;
6437
6438   if (stream->max_buffer_size != 0 && sample_size > stream->max_buffer_size) {
6439     GST_DEBUG_OBJECT (qtdemux,
6440         "size %d larger than stream max_buffer_size %d, trimming",
6441         sample_size, stream->max_buffer_size);
6442     size =
6443         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6444   } else if (stream->min_buffer_size != 0 && stream->offset_in_sample == 0
6445       && sample_size < stream->min_buffer_size) {
6446     guint start_sample_index = stream->sample_index;
6447     guint accumulated_size = sample_size;
6448     guint64 expected_next_offset = offset + sample_size;
6449
6450     GST_DEBUG_OBJECT (qtdemux,
6451         "size %d smaller than stream min_buffer_size %d, combining with the next",
6452         sample_size, stream->min_buffer_size);
6453
6454     while (stream->sample_index < stream->to_sample
6455         && stream->sample_index + 1 < stream->n_samples) {
6456       const QtDemuxSample *next_sample;
6457
6458       /* Increment temporarily */
6459       stream->sample_index++;
6460
6461       /* Failed to parse sample so let's go back to the previous one that was
6462        * still successful */
6463       if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
6464         stream->sample_index--;
6465         break;
6466       }
6467
6468       next_sample = &stream->samples[stream->sample_index];
6469
6470       /* Not contiguous with the previous sample so let's go back to the
6471        * previous one that was still successful */
6472       if (next_sample->offset != expected_next_offset) {
6473         stream->sample_index--;
6474         break;
6475       }
6476
6477       accumulated_size += next_sample->size;
6478       expected_next_offset += next_sample->size;
6479       if (accumulated_size >= stream->min_buffer_size)
6480         break;
6481     }
6482
6483     num_samples = stream->sample_index + 1 - start_sample_index;
6484     stream->sample_index = start_sample_index;
6485     GST_DEBUG_OBJECT (qtdemux, "Pulling %u samples of size %u at once",
6486         num_samples, accumulated_size);
6487     size = accumulated_size;
6488   } else {
6489     size = sample_size;
6490   }
6491
6492   if (qtdemux->cenc_aux_info_offset > 0) {
6493     GstMapInfo map;
6494     GstByteReader br;
6495     GstBuffer *aux_info = NULL;
6496
6497     /* pull the data stored before the sample */
6498     ret =
6499         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6500         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6501     if (G_UNLIKELY (ret != GST_FLOW_OK))
6502       goto beach;
6503     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6504     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6505     gst_byte_reader_init (&br, map.data + 8, map.size);
6506     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6507             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6508       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6509       gst_buffer_unmap (aux_info, &map);
6510       gst_buffer_unref (aux_info);
6511       ret = GST_FLOW_ERROR;
6512       goto beach;
6513     }
6514     gst_buffer_unmap (aux_info, &map);
6515     gst_buffer_unref (aux_info);
6516   }
6517
6518   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6519       offset);
6520
6521   if (stream->use_allocator) {
6522     /* if we have a per-stream allocator, use it */
6523     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6524   }
6525
6526   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6527       size, &buf);
6528   if (G_UNLIKELY (ret != GST_FLOW_OK))
6529     goto beach;
6530
6531   /* Update for both splitting and combining of samples */
6532   if (size != sample_size) {
6533     pts += gst_util_uint64_scale_int (GST_SECOND,
6534         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6535         stream->timescale);
6536     dts +=
6537         gst_util_uint64_scale_int (GST_SECOND,
6538         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6539         stream->timescale);
6540     duration =
6541         gst_util_uint64_scale_int (GST_SECOND,
6542         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6543   }
6544
6545   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6546       dts, pts, duration, keyframe, min_time, offset);
6547
6548   if (size < sample_size) {
6549     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6550     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6551
6552     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6553         sample->timestamp +
6554         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6555     if (time_position >= segment->media_start) {
6556       /* inside the segment, update time_position, looks very familiar to
6557        * GStreamer segments, doesn't it? */
6558       stream->time_position = (time_position - segment->media_start) +
6559           segment->time;
6560     } else {
6561       /* not yet in segment, time does not yet increment. This means
6562        * that we are still prerolling keyframes to the decoder so it can
6563        * decode the first sample of the segment. */
6564       stream->time_position = segment->time;
6565     }
6566   } else if (size > sample_size) {
6567     /* Increase to the last sample we already pulled so that advancing
6568      * below brings us to the next sample we need to pull */
6569     stream->sample_index += num_samples - 1;
6570   }
6571
6572   /* combine flows */
6573   GST_OBJECT_LOCK (qtdemux);
6574   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6575   GST_OBJECT_UNLOCK (qtdemux);
6576   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6577    * we have no more data for the pad to push */
6578   if (ret == GST_FLOW_EOS)
6579     ret = GST_FLOW_OK;
6580
6581   stream->offset_in_sample += size;
6582   if (stream->offset_in_sample >= sample_size) {
6583     gst_qtdemux_advance_sample (qtdemux, stream);
6584   }
6585   goto beach;
6586
6587 next:
6588   gst_qtdemux_advance_sample (qtdemux, stream);
6589
6590 beach:
6591   return ret;
6592
6593   /* special cases */
6594 eos:
6595   {
6596     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6597     ret = GST_FLOW_EOS;
6598     goto beach;
6599   }
6600 eos_stream:
6601   {
6602     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6603     /* EOS will be raised if all are EOS */
6604     ret = GST_FLOW_OK;
6605     goto beach;
6606   }
6607 }
6608
6609 static void
6610 gst_qtdemux_loop (GstPad * pad)
6611 {
6612   GstQTDemux *qtdemux;
6613   guint64 cur_offset;
6614   GstFlowReturn ret;
6615
6616   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6617
6618   cur_offset = qtdemux->offset;
6619   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6620       cur_offset, qt_demux_state_string (qtdemux->state));
6621
6622   switch (qtdemux->state) {
6623     case QTDEMUX_STATE_INITIAL:
6624     case QTDEMUX_STATE_HEADER:
6625       ret = gst_qtdemux_loop_state_header (qtdemux);
6626       break;
6627     case QTDEMUX_STATE_MOVIE:
6628       ret = gst_qtdemux_loop_state_movie (qtdemux);
6629       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6630         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6631       }
6632       break;
6633     default:
6634       /* ouch */
6635       goto invalid_state;
6636   }
6637
6638   /* if something went wrong, pause */
6639   if (ret != GST_FLOW_OK)
6640     goto pause;
6641
6642 done:
6643   gst_object_unref (qtdemux);
6644   return;
6645
6646   /* ERRORS */
6647 invalid_state:
6648   {
6649     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6650         (NULL), ("streaming stopped, invalid state"));
6651     gst_pad_pause_task (pad);
6652     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6653     goto done;
6654   }
6655 pause:
6656   {
6657     const gchar *reason = gst_flow_get_name (ret);
6658
6659     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6660
6661     gst_pad_pause_task (pad);
6662
6663     /* fatal errors need special actions */
6664     /* check EOS */
6665     if (ret == GST_FLOW_EOS) {
6666       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6667         /* we have no streams, post an error */
6668         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6669       }
6670       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6671         gint64 stop;
6672
6673         if ((stop = qtdemux->segment.stop) == -1)
6674           stop = qtdemux->segment.duration;
6675
6676         if (qtdemux->segment.rate >= 0) {
6677           GstMessage *message;
6678           GstEvent *event;
6679
6680           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6681           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6682               GST_FORMAT_TIME, stop);
6683           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6684           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6685             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6686             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6687           }
6688           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6689           gst_qtdemux_push_event (qtdemux, event);
6690         } else {
6691           GstMessage *message;
6692           GstEvent *event;
6693
6694           /*  For Reverse Playback */
6695           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6696           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6697               GST_FORMAT_TIME, qtdemux->segment.start);
6698           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6699               qtdemux->segment.start);
6700           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6701             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6702             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6703           }
6704           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6705           gst_qtdemux_push_event (qtdemux, event);
6706         }
6707       } else {
6708         GstEvent *event;
6709
6710         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6711         event = gst_event_new_eos ();
6712         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6713           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6714         gst_qtdemux_push_event (qtdemux, event);
6715       }
6716     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6717       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6718       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6719     }
6720     goto done;
6721   }
6722 }
6723
6724 /*
6725  * has_next_entry
6726  *
6727  * Returns if there are samples to be played.
6728  */
6729 static gboolean
6730 has_next_entry (GstQTDemux * demux)
6731 {
6732   QtDemuxStream *stream;
6733   gint i;
6734
6735   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6736
6737   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6738     stream = QTDEMUX_NTH_STREAM (demux, i);
6739
6740     if (stream->sample_index == -1) {
6741       stream->sample_index = 0;
6742       stream->offset_in_sample = 0;
6743     }
6744
6745     if (stream->sample_index >= stream->n_samples) {
6746       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6747       continue;
6748     }
6749     GST_DEBUG_OBJECT (demux, "Found a sample");
6750     return TRUE;
6751   }
6752
6753   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6754   return FALSE;
6755 }
6756
6757 /*
6758  * next_entry_size
6759  *
6760  * Returns the size of the first entry at the current offset.
6761  * If -1, there are none (which means EOS or empty file).
6762  */
6763 static guint64
6764 next_entry_size (GstQTDemux * demux)
6765 {
6766   QtDemuxStream *stream, *target_stream = NULL;
6767   guint64 smalloffs = (guint64) - 1;
6768   QtDemuxSample *sample;
6769   gint i;
6770
6771   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6772       demux->offset);
6773
6774   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6775     stream = QTDEMUX_NTH_STREAM (demux, i);
6776
6777     if (stream->sample_index == -1) {
6778       stream->sample_index = 0;
6779       stream->offset_in_sample = 0;
6780     }
6781
6782     if (stream->sample_index >= stream->n_samples) {
6783       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6784       continue;
6785     }
6786
6787     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6788       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6789           stream->sample_index);
6790       return -1;
6791     }
6792
6793     sample = &stream->samples[stream->sample_index];
6794
6795     GST_LOG_OBJECT (demux,
6796         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6797         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6798         stream->sample_index, sample->offset, sample->size);
6799
6800     if (((smalloffs == -1)
6801             || (sample->offset < smalloffs)) && (sample->size)) {
6802       smalloffs = sample->offset;
6803       target_stream = stream;
6804     }
6805   }
6806
6807   if (!target_stream)
6808     return -1;
6809
6810   GST_LOG_OBJECT (demux,
6811       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6812       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6813
6814   stream = target_stream;
6815   sample = &stream->samples[stream->sample_index];
6816
6817   if (sample->offset >= demux->offset) {
6818     demux->todrop = sample->offset - demux->offset;
6819     return sample->size + demux->todrop;
6820   }
6821
6822   GST_DEBUG_OBJECT (demux,
6823       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6824   return -1;
6825 }
6826
6827 static void
6828 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6829 {
6830   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6831
6832   gst_element_post_message (GST_ELEMENT_CAST (demux),
6833       gst_message_new_element (GST_OBJECT_CAST (demux),
6834           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6835 }
6836
6837 static gboolean
6838 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6839 {
6840   GstEvent *event;
6841   gboolean res = 0;
6842
6843   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6844
6845   event =
6846       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6847       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6848       GST_SEEK_TYPE_NONE, -1);
6849
6850   /* store seqnum to drop flush events, they don't need to reach downstream */
6851   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6852   res = gst_pad_push_event (demux->sinkpad, event);
6853   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6854
6855   return res;
6856 }
6857
6858 /* check for seekable upstream, above and beyond a mere query */
6859 static void
6860 gst_qtdemux_check_seekability (GstQTDemux * demux)
6861 {
6862   GstQuery *query;
6863   gboolean seekable = FALSE;
6864   gint64 start = -1, stop = -1;
6865
6866   if (demux->upstream_size)
6867     return;
6868
6869   if (demux->upstream_format_is_time)
6870     return;
6871
6872   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6873   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6874     GST_DEBUG_OBJECT (demux, "seeking query failed");
6875     goto done;
6876   }
6877
6878   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6879
6880   /* try harder to query upstream size if we didn't get it the first time */
6881   if (seekable && stop == -1) {
6882     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6883     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6884   }
6885
6886   /* if upstream doesn't know the size, it's likely that it's not seekable in
6887    * practice even if it technically may be seekable */
6888   if (seekable && (start != 0 || stop <= start)) {
6889     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6890     seekable = FALSE;
6891   }
6892
6893 done:
6894   gst_query_unref (query);
6895
6896   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6897       G_GUINT64_FORMAT ")", seekable, start, stop);
6898   demux->upstream_seekable = seekable;
6899   demux->upstream_size = seekable ? stop : -1;
6900 }
6901
6902 static void
6903 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6904 {
6905   g_return_if_fail (bytes <= demux->todrop);
6906
6907   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6908   gst_adapter_flush (demux->adapter, bytes);
6909   demux->neededbytes -= bytes;
6910   demux->offset += bytes;
6911   demux->todrop -= bytes;
6912 }
6913
6914 /* PUSH-MODE only: Send a segment, if not done already. */
6915 static void
6916 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6917 {
6918   if (G_UNLIKELY (demux->need_segment)) {
6919     gint i;
6920
6921     if (!demux->upstream_format_is_time) {
6922       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6923     } else {
6924       GstEvent *segment_event;
6925       segment_event = gst_event_new_segment (&demux->segment);
6926       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6927         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6928       gst_qtdemux_push_event (demux, segment_event);
6929     }
6930
6931     demux->need_segment = FALSE;
6932
6933     /* clear to send tags on all streams */
6934     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6935       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6936       gst_qtdemux_push_tags (demux, stream);
6937       if (CUR_STREAM (stream)->sparse) {
6938         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6939         gst_pad_push_event (stream->pad,
6940             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6941       }
6942     }
6943   }
6944 }
6945
6946 /* Used for push mode only. */
6947 static void
6948 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6949     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6950 {
6951   GstClockTime ts, dur;
6952
6953   ts = pos;
6954   dur =
6955       stream->segments[segment_index].duration - (pos -
6956       stream->segments[segment_index].time);
6957   stream->time_position += dur;
6958
6959   /* Only gaps with a duration of at least one second are propagated.
6960    * Same workaround as in pull mode.
6961    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6962   if (dur >= GST_SECOND) {
6963     GstEvent *gap;
6964     gap = gst_event_new_gap (ts, dur);
6965
6966     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6967         "segment: %" GST_PTR_FORMAT, gap);
6968     gst_pad_push_event (stream->pad, gap);
6969   }
6970 }
6971
6972 static GstFlowReturn
6973 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6974 {
6975   GstQTDemux *demux;
6976
6977   demux = GST_QTDEMUX (parent);
6978
6979   GST_DEBUG_OBJECT (demux,
6980       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6981       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6982       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6983       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6984       gst_buffer_get_size (inbuf), demux->offset);
6985
6986   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6987     gboolean is_gap_input = FALSE;
6988     gint i;
6989
6990     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6991
6992     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6993       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6994     }
6995
6996     /* Check if we can land back on our feet in the case where upstream is
6997      * handling the seeking/pushing of samples with gaps in between (like
6998      * in the case of trick-mode DASH for example) */
6999     if (demux->upstream_format_is_time
7000         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
7001       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7002         guint32 res;
7003         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
7004         GST_LOG_OBJECT (demux,
7005             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
7006             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
7007         res =
7008             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
7009             stream, GST_BUFFER_OFFSET (inbuf));
7010         if (res != -1) {
7011           QtDemuxSample *sample = &stream->samples[res];
7012           GST_LOG_OBJECT (demux,
7013               "Checking if sample %d from track-id %u is valid (offset:%"
7014               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
7015               stream->track_id, sample->offset, sample->size);
7016           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
7017             GST_LOG_OBJECT (demux,
7018                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
7019                 res);
7020             is_gap_input = TRUE;
7021             /* We can go back to standard playback mode */
7022             demux->state = QTDEMUX_STATE_MOVIE;
7023             /* Remember which sample this stream is at */
7024             stream->sample_index = res;
7025             /* Finally update all push-based values to the expected values */
7026             demux->neededbytes = stream->samples[res].size;
7027             demux->offset = GST_BUFFER_OFFSET (inbuf);
7028             demux->mdatleft =
7029                 demux->mdatsize - demux->offset + demux->mdatoffset;
7030             demux->todrop = 0;
7031           }
7032         }
7033       }
7034       if (!is_gap_input) {
7035         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
7036         /* Reset state if it's a real discont */
7037         demux->neededbytes = 16;
7038         demux->state = QTDEMUX_STATE_INITIAL;
7039         demux->offset = GST_BUFFER_OFFSET (inbuf);
7040         gst_adapter_clear (demux->adapter);
7041       }
7042     }
7043     /* Reverse fragmented playback, need to flush all we have before
7044      * consuming a new fragment.
7045      * The samples array have the timestamps calculated by accumulating the
7046      * durations but this won't work for reverse playback of fragments as
7047      * the timestamps of a subsequent fragment should be smaller than the
7048      * previously received one. */
7049     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
7050       gst_qtdemux_process_adapter (demux, TRUE);
7051       g_ptr_array_foreach (demux->active_streams,
7052           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
7053     }
7054   }
7055
7056   gst_adapter_push (demux->adapter, inbuf);
7057
7058   GST_DEBUG_OBJECT (demux,
7059       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
7060       demux->neededbytes, gst_adapter_available (demux->adapter));
7061
7062   return gst_qtdemux_process_adapter (demux, FALSE);
7063 }
7064
7065 static GstFlowReturn
7066 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
7067 {
7068   GstFlowReturn ret = GST_FLOW_OK;
7069
7070   /* we never really mean to buffer that much */
7071   if (demux->neededbytes == -1) {
7072     goto eos;
7073   }
7074
7075   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
7076       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
7077
7078 #ifndef GST_DISABLE_GST_DEBUG
7079     {
7080       guint64 discont_offset, distance_from_discont;
7081
7082       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
7083       distance_from_discont =
7084           gst_adapter_distance_from_discont (demux->adapter);
7085
7086       GST_DEBUG_OBJECT (demux,
7087           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
7088           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
7089           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
7090           demux->offset, discont_offset, distance_from_discont);
7091     }
7092 #endif
7093
7094     switch (demux->state) {
7095       case QTDEMUX_STATE_INITIAL:{
7096         const guint8 *data;
7097         guint32 fourcc;
7098         guint64 size;
7099
7100         gst_qtdemux_check_seekability (demux);
7101
7102         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7103
7104         /* get fourcc/length, set neededbytes */
7105         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
7106             &size, &fourcc);
7107         gst_adapter_unmap (demux->adapter);
7108         data = NULL;
7109         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7110             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7111         if (size == 0) {
7112           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7113               (_("This file is invalid and cannot be played.")),
7114               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7115                   GST_FOURCC_ARGS (fourcc)));
7116           ret = GST_FLOW_ERROR;
7117           break;
7118         }
7119         if (fourcc == FOURCC_mdat) {
7120           gint next_entry = next_entry_size (demux);
7121           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7122                   || !demux->fragmented)) {
7123             /* we have the headers, start playback */
7124             demux->state = QTDEMUX_STATE_MOVIE;
7125             demux->neededbytes = next_entry;
7126             demux->mdatleft = size;
7127             demux->mdatsize = demux->mdatleft;
7128           } else {
7129             /* no headers yet, try to get them */
7130             guint bs;
7131             gboolean res;
7132             guint64 old, target;
7133
7134           buffer_data:
7135             old = demux->offset;
7136             target = old + size;
7137
7138             /* try to jump over the atom with a seek */
7139             /* only bother if it seems worth doing so,
7140              * and avoids possible upstream/server problems */
7141             if (demux->upstream_seekable &&
7142                 demux->upstream_size > 4 * (1 << 20)) {
7143               res = qtdemux_seek_offset (demux, target);
7144             } else {
7145               GST_DEBUG_OBJECT (demux, "skipping seek");
7146               res = FALSE;
7147             }
7148
7149             if (res) {
7150               GST_DEBUG_OBJECT (demux, "seek success");
7151               /* remember the offset fo the first mdat so we can seek back to it
7152                * after we have the headers */
7153               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7154                 demux->first_mdat = old;
7155                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7156                     demux->first_mdat);
7157               }
7158               /* seek worked, continue reading */
7159               demux->offset = target;
7160               demux->neededbytes = 16;
7161               demux->state = QTDEMUX_STATE_INITIAL;
7162             } else {
7163               /* seek failed, need to buffer */
7164               demux->offset = old;
7165               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7166               /* there may be multiple mdat (or alike) buffers */
7167               /* sanity check */
7168               if (demux->mdatbuffer)
7169                 bs = gst_buffer_get_size (demux->mdatbuffer);
7170               else
7171                 bs = 0;
7172               if (size + bs > 10 * (1 << 20))
7173                 goto no_moov;
7174               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7175               demux->neededbytes = size;
7176               if (!demux->mdatbuffer)
7177                 demux->mdatoffset = demux->offset;
7178             }
7179           }
7180         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7181           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7182               (_("This file is invalid and cannot be played.")),
7183               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7184                   GST_FOURCC_ARGS (fourcc), size));
7185           ret = GST_FLOW_ERROR;
7186           break;
7187         } else {
7188           /* this means we already started buffering and still no moov header,
7189            * let's continue buffering everything till we get moov */
7190           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7191                   || fourcc == FOURCC_moof))
7192             goto buffer_data;
7193           demux->neededbytes = size;
7194           demux->state = QTDEMUX_STATE_HEADER;
7195         }
7196         break;
7197       }
7198       case QTDEMUX_STATE_HEADER:{
7199         const guint8 *data;
7200         guint32 fourcc;
7201
7202         GST_DEBUG_OBJECT (demux, "In header");
7203
7204         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7205
7206         /* parse the header */
7207         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7208             &fourcc);
7209         if (fourcc == FOURCC_moov) {
7210           /* in usual fragmented setup we could try to scan for more
7211            * and end up at the the moov (after mdat) again */
7212           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7213               (!demux->fragmented
7214                   || demux->last_moov_offset == demux->offset)) {
7215             GST_DEBUG_OBJECT (demux,
7216                 "Skipping moov atom as we have (this) one already");
7217           } else {
7218             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7219
7220             if (demux->got_moov && demux->fragmented) {
7221               GST_DEBUG_OBJECT (demux,
7222                   "Got a second moov, clean up data from old one");
7223               if (demux->moov_node_compressed) {
7224                 g_node_destroy (demux->moov_node_compressed);
7225                 if (demux->moov_node)
7226                   g_free (demux->moov_node->data);
7227               }
7228               demux->moov_node_compressed = NULL;
7229               if (demux->moov_node)
7230                 g_node_destroy (demux->moov_node);
7231               demux->moov_node = NULL;
7232             }
7233
7234             demux->last_moov_offset = demux->offset;
7235
7236             /* Update streams with new moov */
7237             gst_qtdemux_stream_concat (demux,
7238                 demux->old_streams, demux->active_streams);
7239
7240             qtdemux_parse_moov (demux, data, demux->neededbytes);
7241             qtdemux_node_dump (demux, demux->moov_node);
7242             qtdemux_parse_tree (demux);
7243             qtdemux_prepare_streams (demux);
7244             QTDEMUX_EXPOSE_LOCK (demux);
7245             qtdemux_expose_streams (demux);
7246             QTDEMUX_EXPOSE_UNLOCK (demux);
7247
7248             demux->got_moov = TRUE;
7249
7250             gst_qtdemux_check_send_pending_segment (demux);
7251
7252             if (demux->moov_node_compressed) {
7253               g_node_destroy (demux->moov_node_compressed);
7254               g_free (demux->moov_node->data);
7255             }
7256             demux->moov_node_compressed = NULL;
7257             g_node_destroy (demux->moov_node);
7258             demux->moov_node = NULL;
7259             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7260           }
7261         } else if (fourcc == FOURCC_moof) {
7262           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7263             guint64 dist = 0;
7264             GstClockTime prev_pts;
7265             guint64 prev_offset;
7266             guint64 adapter_discont_offset, adapter_discont_dist;
7267
7268             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7269
7270             /*
7271              * The timestamp of the moof buffer is relevant as some scenarios
7272              * won't have the initial timestamp in the atoms. Whenever a new
7273              * buffer has started, we get that buffer's PTS and use it as a base
7274              * timestamp for the trun entries.
7275              *
7276              * To keep track of the current buffer timestamp and starting point
7277              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7278              * from the beginning of the buffer, with the distance and demux->offset
7279              * we know if it is still the same buffer or not.
7280              */
7281             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7282             prev_offset = demux->offset - dist;
7283             if (demux->fragment_start_offset == -1
7284                 || prev_offset > demux->fragment_start_offset) {
7285               demux->fragment_start_offset = prev_offset;
7286               demux->fragment_start = prev_pts;
7287               GST_DEBUG_OBJECT (demux,
7288                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7289                   GST_TIME_FORMAT, demux->fragment_start_offset,
7290                   GST_TIME_ARGS (demux->fragment_start));
7291             }
7292
7293             /* We can't use prev_offset() here because this would require
7294              * upstream to set consistent and correct offsets on all buffers
7295              * since the discont. Nothing ever did that in the past and we
7296              * would break backwards compatibility here then.
7297              * Instead take the offset we had at the last discont and count
7298              * the bytes from there. This works with old code as there would
7299              * be no discont between moov and moof, and also works with
7300              * adaptivedemux which correctly sets offset and will set the
7301              * DISCONT flag accordingly when needed.
7302              *
7303              * We also only do this for upstream TIME segments as otherwise
7304              * there are potential backwards compatibility problems with
7305              * seeking in PUSH mode and upstream providing inconsistent
7306              * timestamps. */
7307             adapter_discont_offset =
7308                 gst_adapter_offset_at_discont (demux->adapter);
7309             adapter_discont_dist =
7310                 gst_adapter_distance_from_discont (demux->adapter);
7311
7312             GST_DEBUG_OBJECT (demux,
7313                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7314                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7315                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7316
7317             if (demux->upstream_format_is_time) {
7318               demux->moof_offset = adapter_discont_offset;
7319               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7320                 demux->moof_offset += adapter_discont_dist;
7321               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7322                 demux->moof_offset = demux->offset;
7323             } else {
7324               demux->moof_offset = demux->offset;
7325             }
7326
7327             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7328                     demux->moof_offset, NULL)) {
7329               gst_adapter_unmap (demux->adapter);
7330               ret = GST_FLOW_ERROR;
7331               goto done;
7332             }
7333
7334             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7335             if (demux->mss_mode && !demux->exposed) {
7336               QTDEMUX_EXPOSE_LOCK (demux);
7337               qtdemux_expose_streams (demux);
7338               QTDEMUX_EXPOSE_UNLOCK (demux);
7339             }
7340
7341             gst_qtdemux_check_send_pending_segment (demux);
7342           } else {
7343             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7344           }
7345         } else if (fourcc == FOURCC_ftyp) {
7346           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7347           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7348         } else if (fourcc == FOURCC_uuid) {
7349           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7350           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7351         } else if (fourcc == FOURCC_sidx) {
7352           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7353           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7354         } else {
7355           switch (fourcc) {
7356             case FOURCC_styp:
7357               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7358                * FALLTHROUGH */
7359             case FOURCC_skip:
7360             case FOURCC_free:
7361               /* [free] and [skip] are padding atoms */
7362               GST_DEBUG_OBJECT (demux,
7363                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7364                   GST_FOURCC_ARGS (fourcc));
7365               break;
7366             default:
7367               GST_WARNING_OBJECT (demux,
7368                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7369                   GST_FOURCC_ARGS (fourcc));
7370               /* Let's jump that one and go back to initial state */
7371               break;
7372           }
7373         }
7374         gst_adapter_unmap (demux->adapter);
7375         data = NULL;
7376
7377         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7378           gsize remaining_data_size = 0;
7379
7380           /* the mdat was before the header */
7381           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7382               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7383           /* restore our adapter/offset view of things with upstream;
7384            * put preceding buffered data ahead of current moov data.
7385            * This should also handle evil mdat, moov, mdat cases and alike */
7386           gst_adapter_flush (demux->adapter, demux->neededbytes);
7387
7388           /* Store any remaining data after the mdat for later usage */
7389           remaining_data_size = gst_adapter_available (demux->adapter);
7390           if (remaining_data_size > 0) {
7391             g_assert (demux->restoredata_buffer == NULL);
7392             demux->restoredata_buffer =
7393                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7394             demux->restoredata_offset = demux->offset + demux->neededbytes;
7395             GST_DEBUG_OBJECT (demux,
7396                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7397                 G_GUINT64_FORMAT, remaining_data_size,
7398                 demux->restoredata_offset);
7399           }
7400
7401           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7402           demux->mdatbuffer = NULL;
7403           demux->offset = demux->mdatoffset;
7404           demux->neededbytes = next_entry_size (demux);
7405           demux->state = QTDEMUX_STATE_MOVIE;
7406           demux->mdatleft = gst_adapter_available (demux->adapter);
7407           demux->mdatsize = demux->mdatleft;
7408         } else {
7409           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7410           gst_adapter_flush (demux->adapter, demux->neededbytes);
7411
7412           /* only go back to the mdat if there are samples to play */
7413           if (demux->got_moov && demux->first_mdat != -1
7414               && has_next_entry (demux)) {
7415             gboolean res;
7416
7417             /* we need to seek back */
7418             res = qtdemux_seek_offset (demux, demux->first_mdat);
7419             if (res) {
7420               demux->offset = demux->first_mdat;
7421             } else {
7422               GST_DEBUG_OBJECT (demux, "Seek back failed");
7423             }
7424           } else {
7425             demux->offset += demux->neededbytes;
7426           }
7427           demux->neededbytes = 16;
7428           demux->state = QTDEMUX_STATE_INITIAL;
7429         }
7430
7431         break;
7432       }
7433       case QTDEMUX_STATE_BUFFER_MDAT:{
7434         GstBuffer *buf;
7435         guint8 fourcc[4];
7436
7437         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7438             demux->offset);
7439         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7440         gst_buffer_extract (buf, 0, fourcc, 4);
7441         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7442             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7443         if (demux->mdatbuffer)
7444           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7445         else
7446           demux->mdatbuffer = buf;
7447         demux->offset += demux->neededbytes;
7448         demux->neededbytes = 16;
7449         demux->state = QTDEMUX_STATE_INITIAL;
7450         gst_qtdemux_post_progress (demux, 1, 1);
7451
7452         break;
7453       }
7454       case QTDEMUX_STATE_MOVIE:{
7455         QtDemuxStream *stream = NULL;
7456         QtDemuxSample *sample;
7457         GstClockTime dts, pts, duration;
7458         gboolean keyframe;
7459         gint i;
7460
7461         GST_DEBUG_OBJECT (demux,
7462             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7463
7464         if (demux->fragmented) {
7465           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7466               demux->mdatleft);
7467           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7468             /* if needed data starts within this atom,
7469              * then it should not exceed this atom */
7470             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7471               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7472                   (_("This file is invalid and cannot be played.")),
7473                   ("sample data crosses atom boundary"));
7474               ret = GST_FLOW_ERROR;
7475               break;
7476             }
7477             demux->mdatleft -= demux->neededbytes;
7478           } else {
7479             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7480             /* so we are dropping more than left in this atom */
7481             gst_qtdemux_drop_data (demux, demux->mdatleft);
7482             demux->mdatleft = 0;
7483
7484             /* need to resume atom parsing so we do not miss any other pieces */
7485             demux->state = QTDEMUX_STATE_INITIAL;
7486             demux->neededbytes = 16;
7487
7488             /* check if there was any stored post mdat data from previous buffers */
7489             if (demux->restoredata_buffer) {
7490               g_assert (gst_adapter_available (demux->adapter) == 0);
7491
7492               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7493               demux->restoredata_buffer = NULL;
7494               demux->offset = demux->restoredata_offset;
7495             }
7496
7497             break;
7498           }
7499         }
7500
7501         if (demux->todrop) {
7502           if (demux->cenc_aux_info_offset > 0) {
7503             GstByteReader br;
7504             const guint8 *data;
7505
7506             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7507             data = gst_adapter_map (demux->adapter, demux->todrop);
7508             gst_byte_reader_init (&br, data + 8, demux->todrop);
7509             if (!qtdemux_parse_cenc_aux_info (demux,
7510                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7511                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7512               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7513               ret = GST_FLOW_ERROR;
7514               gst_adapter_unmap (demux->adapter);
7515               g_free (demux->cenc_aux_info_sizes);
7516               demux->cenc_aux_info_sizes = NULL;
7517               goto done;
7518             }
7519             demux->cenc_aux_info_offset = 0;
7520             g_free (demux->cenc_aux_info_sizes);
7521             demux->cenc_aux_info_sizes = NULL;
7522             gst_adapter_unmap (demux->adapter);
7523           }
7524           gst_qtdemux_drop_data (demux, demux->todrop);
7525         }
7526
7527         /* first buffer? */
7528         /* initial newsegment sent here after having added pads,
7529          * possible others in sink_event */
7530         gst_qtdemux_check_send_pending_segment (demux);
7531
7532         /* Figure out which stream this packet belongs to */
7533         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7534           stream = QTDEMUX_NTH_STREAM (demux, i);
7535           if (stream->sample_index >= stream->n_samples) {
7536             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7537             stream = NULL;
7538             continue;
7539           }
7540           GST_LOG_OBJECT (demux,
7541               "Checking track-id %u (sample_index:%d / offset:%"
7542               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7543               stream->sample_index,
7544               stream->samples[stream->sample_index].offset,
7545               stream->samples[stream->sample_index].size);
7546
7547           if (stream->samples[stream->sample_index].offset == demux->offset)
7548             break;
7549         }
7550
7551         if (G_UNLIKELY (stream == NULL))
7552           goto unknown_stream;
7553
7554         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7555
7556         if (stream->new_caps) {
7557           gst_qtdemux_configure_stream (demux, stream);
7558         }
7559
7560         /* Put data in a buffer, set timestamps, caps, ... */
7561         sample = &stream->samples[stream->sample_index];
7562
7563         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7564           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7565               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7566
7567           dts = QTSAMPLE_DTS (stream, sample);
7568           pts = QTSAMPLE_PTS (stream, sample);
7569           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7570           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7571
7572           /* check for segment end */
7573           if (G_UNLIKELY (demux->segment.stop != -1
7574                   && demux->segment.stop <= pts && stream->on_keyframe)
7575               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7576             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7577             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7578
7579             /* skip this data, stream is EOS */
7580             gst_adapter_flush (demux->adapter, demux->neededbytes);
7581             demux->offset += demux->neededbytes;
7582
7583             /* check if all streams are eos */
7584             ret = GST_FLOW_EOS;
7585             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7586               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7587                 ret = GST_FLOW_OK;
7588                 break;
7589               }
7590             }
7591           } else {
7592             GstBuffer *outbuf;
7593
7594             outbuf =
7595                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7596
7597             /* FIXME: should either be an assert or a plain check */
7598             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7599
7600             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7601                 dts, pts, duration, keyframe, dts, demux->offset);
7602           }
7603
7604           /* combine flows */
7605           GST_OBJECT_LOCK (demux);
7606           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7607           GST_OBJECT_UNLOCK (demux);
7608         } else {
7609           /* skip this data, stream is EOS */
7610           gst_adapter_flush (demux->adapter, demux->neededbytes);
7611         }
7612
7613         stream->sample_index++;
7614         stream->offset_in_sample = 0;
7615
7616         /* update current offset and figure out size of next buffer */
7617         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7618             demux->offset, demux->neededbytes);
7619         demux->offset += demux->neededbytes;
7620         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7621             demux->offset);
7622
7623
7624         if (ret == GST_FLOW_EOS) {
7625           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7626           demux->neededbytes = -1;
7627           goto eos;
7628         }
7629
7630         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7631           if (demux->fragmented) {
7632             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7633             /* there may be more to follow, only finish this atom */
7634             demux->todrop = demux->mdatleft;
7635             demux->neededbytes = demux->todrop;
7636             break;
7637           }
7638           goto eos;
7639         }
7640         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7641           goto non_ok_unlinked_flow;
7642         }
7643         break;
7644       }
7645       default:
7646         goto invalid_state;
7647     }
7648   }
7649
7650   /* when buffering movie data, at least show user something is happening */
7651   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7652       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7653     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7654         demux->neededbytes);
7655   }
7656 done:
7657
7658   return ret;
7659
7660   /* ERRORS */
7661 non_ok_unlinked_flow:
7662   {
7663     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7664         gst_flow_get_name (ret));
7665     return ret;
7666   }
7667 unknown_stream:
7668   {
7669     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7670     ret = GST_FLOW_ERROR;
7671     goto done;
7672   }
7673 eos:
7674   {
7675     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7676     ret = GST_FLOW_EOS;
7677     goto done;
7678   }
7679 invalid_state:
7680   {
7681     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7682         (NULL), ("qtdemuxer invalid state %d", demux->state));
7683     ret = GST_FLOW_ERROR;
7684     goto done;
7685   }
7686 no_moov:
7687   {
7688     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7689         (NULL), ("no 'moov' atom within the first 10 MB"));
7690     ret = GST_FLOW_ERROR;
7691     goto done;
7692   }
7693 }
7694
7695 static gboolean
7696 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7697 {
7698   GstQuery *query;
7699   gboolean pull_mode;
7700
7701   query = gst_query_new_scheduling ();
7702
7703   if (!gst_pad_peer_query (sinkpad, query)) {
7704     gst_query_unref (query);
7705     goto activate_push;
7706   }
7707
7708   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7709       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7710   gst_query_unref (query);
7711
7712   if (!pull_mode)
7713     goto activate_push;
7714
7715   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7716   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7717
7718 activate_push:
7719   {
7720     GST_DEBUG_OBJECT (sinkpad, "activating push");
7721     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7722   }
7723 }
7724
7725 static gboolean
7726 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7727     GstPadMode mode, gboolean active)
7728 {
7729   gboolean res;
7730   GstQTDemux *demux = GST_QTDEMUX (parent);
7731
7732   switch (mode) {
7733     case GST_PAD_MODE_PUSH:
7734       demux->pullbased = FALSE;
7735       res = TRUE;
7736       break;
7737     case GST_PAD_MODE_PULL:
7738       if (active) {
7739         demux->pullbased = TRUE;
7740         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7741             sinkpad, NULL);
7742       } else {
7743         res = gst_pad_stop_task (sinkpad);
7744       }
7745       break;
7746     default:
7747       res = FALSE;
7748       break;
7749   }
7750   return res;
7751 }
7752
7753 #ifdef HAVE_ZLIB
7754 static void *
7755 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7756 {
7757   guint8 *buffer;
7758   z_stream z;
7759   int ret;
7760
7761   memset (&z, 0, sizeof (z));
7762   z.zalloc = NULL;
7763   z.zfree = NULL;
7764   z.opaque = NULL;
7765
7766   if ((ret = inflateInit (&z)) != Z_OK) {
7767     GST_ERROR ("inflateInit() returned %d", ret);
7768     return NULL;
7769   }
7770
7771   z.next_in = z_buffer;
7772   z.avail_in = z_length;
7773
7774   buffer = (guint8 *) g_malloc (*length);
7775   z.avail_out = *length;
7776   z.next_out = (Bytef *) buffer;
7777   do {
7778     ret = inflate (&z, Z_NO_FLUSH);
7779     if (ret == Z_STREAM_END) {
7780       break;
7781     } else if (ret != Z_OK) {
7782       GST_WARNING ("inflate() returned %d", ret);
7783       break;
7784     }
7785
7786     *length += 4096;
7787     buffer = (guint8 *) g_realloc (buffer, *length);
7788     z.next_out = (Bytef *) (buffer + z.total_out);
7789     z.avail_out += 4096;
7790   } while (z.avail_in > 0);
7791
7792   if (ret != Z_STREAM_END) {
7793     g_free (buffer);
7794     buffer = NULL;
7795     *length = 0;
7796   } else {
7797     *length = z.total_out;
7798   }
7799
7800   inflateEnd (&z);
7801
7802   return buffer;
7803 }
7804 #endif /* HAVE_ZLIB */
7805
7806 static gboolean
7807 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7808 {
7809   GNode *cmov;
7810
7811   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7812
7813   /* counts as header data */
7814   qtdemux->header_size += length;
7815
7816   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7817   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7818
7819   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7820   if (cmov) {
7821     guint32 method;
7822     GNode *dcom;
7823     GNode *cmvd;
7824     guint32 dcom_len;
7825
7826     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7827     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7828     if (dcom == NULL || cmvd == NULL)
7829       goto invalid_compression;
7830
7831     dcom_len = QT_UINT32 (dcom->data);
7832     if (dcom_len < 12)
7833       goto invalid_compression;
7834
7835     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7836     switch (method) {
7837 #ifdef HAVE_ZLIB
7838       case FOURCC_zlib:{
7839         guint uncompressed_length;
7840         guint compressed_length;
7841         guint8 *buf;
7842         guint32 cmvd_len;
7843
7844         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7845         if (cmvd_len < 12)
7846           goto invalid_compression;
7847
7848         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7849         compressed_length = cmvd_len - 12;
7850         GST_LOG ("length = %u", uncompressed_length);
7851
7852         buf =
7853             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7854             compressed_length, &uncompressed_length);
7855
7856         if (buf) {
7857           qtdemux->moov_node_compressed = qtdemux->moov_node;
7858           qtdemux->moov_node = g_node_new (buf);
7859
7860           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7861               uncompressed_length);
7862         }
7863         break;
7864       }
7865 #endif /* HAVE_ZLIB */
7866       default:
7867         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7868             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7869         break;
7870     }
7871   }
7872   return TRUE;
7873
7874   /* ERRORS */
7875 invalid_compression:
7876   {
7877     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7878     return FALSE;
7879   }
7880 }
7881
7882 static gboolean
7883 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7884     const guint8 * end)
7885 {
7886   while (G_UNLIKELY (buf < end)) {
7887     GNode *child;
7888     guint32 len;
7889
7890     if (G_UNLIKELY (buf + 4 > end)) {
7891       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7892       break;
7893     }
7894     len = QT_UINT32 (buf);
7895     if (G_UNLIKELY (len == 0)) {
7896       GST_LOG_OBJECT (qtdemux, "empty container");
7897       break;
7898     }
7899     if (G_UNLIKELY (len < 8)) {
7900       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7901       break;
7902     }
7903     if (G_UNLIKELY (len > (end - buf))) {
7904       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7905           (gint) (end - buf));
7906       break;
7907     }
7908
7909     child = g_node_new ((guint8 *) buf);
7910     g_node_append (node, child);
7911     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7912     qtdemux_parse_node (qtdemux, child, buf, len);
7913
7914     buf += len;
7915   }
7916   return TRUE;
7917 }
7918
7919 static gboolean
7920 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7921     GNode * xdxt)
7922 {
7923   int len = QT_UINT32 (xdxt->data);
7924   guint8 *buf = xdxt->data;
7925   guint8 *end = buf + len;
7926   GstBuffer *buffer;
7927
7928   /* skip size and type */
7929   buf += 8;
7930   end -= 8;
7931
7932   while (buf < end) {
7933     gint size;
7934     guint32 type;
7935
7936     size = QT_UINT32 (buf);
7937     type = QT_FOURCC (buf + 4);
7938
7939     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7940
7941     if (buf + size > end || size <= 0)
7942       break;
7943
7944     buf += 8;
7945     size -= 8;
7946
7947     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7948         GST_FOURCC_ARGS (type));
7949
7950     switch (type) {
7951       case FOURCC_tCtH:
7952         buffer = gst_buffer_new_and_alloc (size);
7953         gst_buffer_fill (buffer, 0, buf, size);
7954         stream->buffers = g_slist_append (stream->buffers, buffer);
7955         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7956         break;
7957       case FOURCC_tCt_:
7958         buffer = gst_buffer_new_and_alloc (size);
7959         gst_buffer_fill (buffer, 0, buf, size);
7960         stream->buffers = g_slist_append (stream->buffers, buffer);
7961         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7962         break;
7963       case FOURCC_tCtC:
7964         buffer = gst_buffer_new_and_alloc (size);
7965         gst_buffer_fill (buffer, 0, buf, size);
7966         stream->buffers = g_slist_append (stream->buffers, buffer);
7967         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7968         break;
7969       default:
7970         GST_WARNING_OBJECT (qtdemux,
7971             "unknown theora cookie %" GST_FOURCC_FORMAT,
7972             GST_FOURCC_ARGS (type));
7973         break;
7974     }
7975     buf += size;
7976   }
7977   return TRUE;
7978 }
7979
7980 static gboolean
7981 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7982     guint length)
7983 {
7984   guint32 fourcc = 0;
7985   guint32 node_length = 0;
7986   const QtNodeType *type;
7987   const guint8 *end;
7988
7989   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7990
7991   if (G_UNLIKELY (length < 8))
7992     goto not_enough_data;
7993
7994   node_length = QT_UINT32 (buffer);
7995   fourcc = QT_FOURCC (buffer + 4);
7996
7997   /* ignore empty nodes */
7998   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7999     return TRUE;
8000
8001   type = qtdemux_type_get (fourcc);
8002
8003   end = buffer + length;
8004
8005   GST_LOG_OBJECT (qtdemux,
8006       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
8007       GST_FOURCC_ARGS (fourcc), node_length, type->name);
8008
8009   if (node_length > length)
8010     goto broken_atom_size;
8011
8012   if (type->flags & QT_FLAG_CONTAINER) {
8013     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8014   } else {
8015     switch (fourcc) {
8016       case FOURCC_stsd:
8017       {
8018         if (node_length < 20) {
8019           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
8020           break;
8021         }
8022         GST_DEBUG_OBJECT (qtdemux,
8023             "parsing stsd (sample table, sample description) atom");
8024         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
8025         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8026         break;
8027       }
8028       case FOURCC_mp4a:
8029       case FOURCC_alac:
8030       case FOURCC_fLaC:
8031       case FOURCC_aavd:
8032       {
8033         guint32 version;
8034         guint32 offset;
8035         guint min_size;
8036
8037         /* also read alac (or whatever) in stead of mp4a in the following,
8038          * since a similar layout is used in other cases as well */
8039         if (fourcc == FOURCC_mp4a)
8040           min_size = 20;
8041         else if (fourcc == FOURCC_fLaC)
8042           min_size = 86;
8043         else
8044           min_size = 40;
8045
8046         /* There are two things we might encounter here: a true mp4a atom, and
8047            an mp4a entry in an stsd atom. The latter is what we're interested
8048            in, and it looks like an atom, but isn't really one. The true mp4a
8049            atom is short, so we detect it based on length here. */
8050         if (length < min_size) {
8051           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8052               GST_FOURCC_ARGS (fourcc));
8053           break;
8054         }
8055
8056         /* 'version' here is the sound sample description version. Types 0 and
8057            1 are documented in the QTFF reference, but type 2 is not: it's
8058            described in Apple header files instead (struct SoundDescriptionV2
8059            in Movies.h) */
8060         version = QT_UINT16 (buffer + 16);
8061
8062         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
8063             GST_FOURCC_ARGS (fourcc), version);
8064
8065         /* parse any esds descriptors */
8066         switch (version) {
8067           case 0:
8068             offset = 0x24;
8069             break;
8070           case 1:
8071             offset = 0x34;
8072             break;
8073           case 2:
8074             offset = 0x48;
8075             break;
8076           default:
8077             GST_WARNING_OBJECT (qtdemux,
8078                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
8079                 GST_FOURCC_ARGS (fourcc), version);
8080             offset = 0;
8081             break;
8082         }
8083         if (offset)
8084           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8085         break;
8086       }
8087       case FOURCC_mp4v:
8088       case FOURCC_MP4V:
8089       case FOURCC_fmp4:
8090       case FOURCC_FMP4:
8091       case FOURCC_apcs:
8092       case FOURCC_apch:
8093       case FOURCC_apcn:
8094       case FOURCC_apco:
8095       case FOURCC_ap4h:
8096       case FOURCC_xvid:
8097       case FOURCC_XVID:
8098       case FOURCC_H264:
8099       case FOURCC_avc1:
8100       case FOURCC_avc3:
8101       case FOURCC_H265:
8102       case FOURCC_hvc1:
8103       case FOURCC_hev1:
8104       case FOURCC_dvh1:
8105       case FOURCC_dvhe:
8106       case FOURCC_mjp2:
8107       case FOURCC_encv:
8108       {
8109         guint32 version;
8110         guint32 str_len;
8111
8112         /* codec_data is contained inside these atoms, which all have
8113          * the same format. */
8114         /* video sample description size is 86 bytes without extension.
8115          * node_length have to be bigger than 86 bytes because video sample
8116          * description can include extensions such as esds, fiel, glbl, etc. */
8117         if (node_length < 86) {
8118           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8119               " sample description length too short (%u < 86)",
8120               GST_FOURCC_ARGS (fourcc), node_length);
8121           break;
8122         }
8123
8124         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8125             GST_FOURCC_ARGS (fourcc));
8126
8127         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8128          *              its data format.
8129          * revision level (2 bytes) : must be set to 0. */
8130         version = QT_UINT32 (buffer + 16);
8131         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8132
8133         /* compressor name : PASCAL string and informative purposes
8134          * first byte : the number of bytes to be displayed.
8135          *              it has to be less than 32 because it is reserved
8136          *              space of 32 bytes total including itself. */
8137         str_len = QT_UINT8 (buffer + 50);
8138         if (str_len < 32)
8139           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8140               (char *) buffer + 51);
8141         else
8142           GST_WARNING_OBJECT (qtdemux,
8143               "compressorname length too big (%u > 31)", str_len);
8144
8145         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8146             end - buffer);
8147         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8148         break;
8149       }
8150       case FOURCC_meta:
8151       {
8152         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8153
8154         /* You are reading this correctly. QTFF specifies that the
8155          * metadata atom is a short atom, whereas ISO BMFF specifies
8156          * it's a full atom. But since so many people are doing things
8157          * differently, we actually peek into the atom to see which
8158          * variant it is */
8159         if (length < 16) {
8160           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8161               GST_FOURCC_ARGS (fourcc));
8162           break;
8163         }
8164         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8165           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8166            * starts with a 'hdlr' atom */
8167           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8168         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8169           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8170            * with version/flags both set to zero */
8171           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8172         } else
8173           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8174         break;
8175       }
8176       case FOURCC_mp4s:
8177       {
8178         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8179         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8180         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8181         break;
8182       }
8183       case FOURCC_XiTh:
8184       {
8185         guint32 version;
8186         guint32 offset;
8187
8188         if (length < 16) {
8189           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8190               GST_FOURCC_ARGS (fourcc));
8191           break;
8192         }
8193
8194         version = QT_UINT32 (buffer + 12);
8195         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8196
8197         switch (version) {
8198           case 0x00000001:
8199             offset = 0x62;
8200             break;
8201           default:
8202             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8203             offset = 0;
8204             break;
8205         }
8206         if (offset) {
8207           if (length < offset) {
8208             GST_WARNING_OBJECT (qtdemux,
8209                 "skipping too small %" GST_FOURCC_FORMAT " box",
8210                 GST_FOURCC_ARGS (fourcc));
8211             break;
8212           }
8213           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8214         }
8215         break;
8216       }
8217       case FOURCC_in24:
8218       {
8219         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8220         break;
8221       }
8222       case FOURCC_uuid:
8223       {
8224         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8225         break;
8226       }
8227       case FOURCC_enca:
8228       {
8229         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8230         break;
8231       }
8232       default:
8233         if (!strcmp (type->name, "unknown"))
8234           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8235         break;
8236     }
8237   }
8238   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8239       GST_FOURCC_ARGS (fourcc));
8240   return TRUE;
8241
8242 /* ERRORS */
8243 not_enough_data:
8244   {
8245     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8246         (_("This file is corrupt and cannot be played.")),
8247         ("Not enough data for an atom header, got only %u bytes", length));
8248     return FALSE;
8249   }
8250 broken_atom_size:
8251   {
8252     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8253         (_("This file is corrupt and cannot be played.")),
8254         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8255             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8256             length));
8257     return FALSE;
8258   }
8259 }
8260
8261 static void
8262 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8263 {
8264 /* FIXME: This can only reliably work if demuxers have a
8265  * separate streaming thread per srcpad. This should be
8266  * done in a demuxer base class, which integrates parts
8267  * of multiqueue
8268  *
8269  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8270  */
8271 #if 0
8272   GstQuery *query;
8273
8274   query = gst_query_new_allocation (stream->caps, FALSE);
8275
8276   if (!gst_pad_peer_query (stream->pad, query)) {
8277     /* not a problem, just debug a little */
8278     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8279   }
8280
8281   if (stream->allocator)
8282     gst_object_unref (stream->allocator);
8283
8284   if (gst_query_get_n_allocation_params (query) > 0) {
8285     /* try the allocator */
8286     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8287         &stream->params);
8288     stream->use_allocator = TRUE;
8289   } else {
8290     stream->allocator = NULL;
8291     gst_allocation_params_init (&stream->params);
8292     stream->use_allocator = FALSE;
8293   }
8294   gst_query_unref (query);
8295 #endif
8296 }
8297
8298 static gboolean
8299 pad_query (const GValue * item, GValue * value, gpointer user_data)
8300 {
8301   GstPad *pad = g_value_get_object (item);
8302   GstQuery *query = user_data;
8303   gboolean res;
8304
8305   res = gst_pad_peer_query (pad, query);
8306
8307   if (res) {
8308     g_value_set_boolean (value, TRUE);
8309     return FALSE;
8310   }
8311
8312   GST_INFO_OBJECT (pad, "pad peer query failed");
8313   return TRUE;
8314 }
8315
8316 static gboolean
8317 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8318     GstPadDirection direction)
8319 {
8320   GstIterator *it;
8321   GstIteratorFoldFunction func = pad_query;
8322   GValue res = { 0, };
8323
8324   g_value_init (&res, G_TYPE_BOOLEAN);
8325   g_value_set_boolean (&res, FALSE);
8326
8327   /* Ask neighbor */
8328   if (direction == GST_PAD_SRC)
8329     it = gst_element_iterate_src_pads (element);
8330   else
8331     it = gst_element_iterate_sink_pads (element);
8332
8333   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8334     gst_iterator_resync (it);
8335
8336   gst_iterator_free (it);
8337
8338   return g_value_get_boolean (&res);
8339 }
8340
8341 static void
8342 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8343     QtDemuxStream * stream)
8344 {
8345   GstQuery *query;
8346   GstContext *ctxt;
8347   GstElement *element = GST_ELEMENT (qtdemux);
8348   GstStructure *st;
8349   gchar **filtered_sys_ids;
8350   GValue event_list = G_VALUE_INIT;
8351   GList *walk;
8352
8353   /* 1. Check if we already have the context. */
8354   if (qtdemux->preferred_protection_system_id != NULL) {
8355     GST_LOG_OBJECT (element,
8356         "already have the protection context, no need to request it again");
8357     return;
8358   }
8359
8360   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8361   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8362       (const gchar **) qtdemux->protection_system_ids->pdata);
8363
8364   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8365       qtdemux->protection_system_ids->len - 1);
8366   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8367       "decryptors for %u of them, running context request",
8368       qtdemux->protection_system_ids->len,
8369       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8370
8371
8372   if (stream->protection_scheme_event_queue.length) {
8373     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8374         stream->protection_scheme_event_queue.length);
8375     walk = stream->protection_scheme_event_queue.tail;
8376   } else {
8377     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8378         qtdemux->protection_event_queue.length);
8379     walk = qtdemux->protection_event_queue.tail;
8380   }
8381
8382   g_value_init (&event_list, GST_TYPE_LIST);
8383   for (; walk; walk = g_list_previous (walk)) {
8384     GValue *event_value = g_new0 (GValue, 1);
8385     g_value_init (event_value, GST_TYPE_EVENT);
8386     g_value_set_boxed (event_value, walk->data);
8387     gst_value_list_append_and_take_value (&event_list, event_value);
8388   }
8389
8390   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8391    *      check if downstream already has a context of the specific type
8392    *  2b) Query upstream as above.
8393    */
8394   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8395   st = gst_query_writable_structure (query);
8396   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8397       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8398       NULL);
8399   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8400   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8401     gst_query_parse_context (query, &ctxt);
8402     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8403     gst_element_set_context (element, ctxt);
8404   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8405     gst_query_parse_context (query, &ctxt);
8406     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8407     gst_element_set_context (element, ctxt);
8408   } else {
8409     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8410      *    the required context type and afterwards check if a
8411      *    usable context was set now as in 1). The message could
8412      *    be handled by the parent bins of the element and the
8413      *    application.
8414      */
8415     GstMessage *msg;
8416
8417     GST_INFO_OBJECT (element, "posting need context message");
8418     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8419         "drm-preferred-decryption-system-id");
8420     st = (GstStructure *) gst_message_get_structure (msg);
8421     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8422         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8423         NULL);
8424
8425     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8426     gst_element_post_message (element, msg);
8427   }
8428
8429   g_strfreev (filtered_sys_ids);
8430   g_value_unset (&event_list);
8431   gst_query_unref (query);
8432 }
8433
8434 static gboolean
8435 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8436     QtDemuxStream * stream)
8437 {
8438   GstStructure *s;
8439   const gchar *selected_system = NULL;
8440
8441   g_return_val_if_fail (qtdemux != NULL, FALSE);
8442   g_return_val_if_fail (stream != NULL, FALSE);
8443   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8444       FALSE);
8445
8446   if (stream->protection_scheme_type == FOURCC_aavd) {
8447     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8448     if (!gst_structure_has_name (s, "application/x-aavd")) {
8449       gst_structure_set (s,
8450           "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8451           NULL);
8452       gst_structure_set_name (s, "application/x-aavd");
8453     }
8454     return TRUE;
8455   }
8456
8457   if (stream->protection_scheme_type != FOURCC_cenc
8458       && stream->protection_scheme_type != FOURCC_cbcs) {
8459     GST_ERROR_OBJECT (qtdemux,
8460         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8461         GST_FOURCC_ARGS (stream->protection_scheme_type));
8462     return FALSE;
8463   }
8464
8465   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8466   if (!gst_structure_has_name (s, "application/x-cenc")) {
8467     gst_structure_set (s,
8468         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL);
8469     gst_structure_set (s, "cipher-mode", G_TYPE_STRING,
8470         (stream->protection_scheme_type == FOURCC_cbcs) ? "cbcs" : "cenc",
8471         NULL);
8472     gst_structure_set_name (s, "application/x-cenc");
8473   }
8474
8475   if (qtdemux->protection_system_ids == NULL) {
8476     GST_DEBUG_OBJECT (qtdemux, "stream is protected using cenc, but no "
8477         "cenc protection system information has been found, not setting a "
8478         "protection system UUID");
8479     return TRUE;
8480   }
8481
8482   gst_qtdemux_request_protection_context (qtdemux, stream);
8483   if (qtdemux->preferred_protection_system_id != NULL) {
8484     const gchar *preferred_system_array[] =
8485         { qtdemux->preferred_protection_system_id, NULL };
8486
8487     selected_system = gst_protection_select_system (preferred_system_array);
8488
8489     if (selected_system) {
8490       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8491           qtdemux->preferred_protection_system_id);
8492     } else {
8493       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8494           "because there is no available decryptor",
8495           qtdemux->preferred_protection_system_id);
8496     }
8497   }
8498
8499   if (!selected_system) {
8500     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8501     selected_system = gst_protection_select_system ((const gchar **)
8502         qtdemux->protection_system_ids->pdata);
8503     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8504         qtdemux->protection_system_ids->len - 1);
8505   }
8506
8507   if (!selected_system) {
8508     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8509         "suitable decryptor element has been found");
8510     return FALSE;
8511   }
8512
8513   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8514       selected_system);
8515
8516   gst_structure_set (s,
8517       GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8518       NULL);
8519
8520   return TRUE;
8521 }
8522
8523 static gboolean
8524 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8525 {
8526   /* fps is calculated base on the duration of the average framerate since
8527    * qt does not have a fixed framerate. */
8528   gboolean fps_available = TRUE;
8529   guint32 first_duration = 0;
8530
8531   if (stream->n_samples > 0)
8532     first_duration = stream->samples[0].duration;
8533
8534   if ((stream->n_samples == 1 && first_duration == 0)
8535       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8536     /* still frame */
8537     CUR_STREAM (stream)->fps_n = 0;
8538     CUR_STREAM (stream)->fps_d = 1;
8539   } else {
8540     if (stream->duration == 0 || stream->n_samples < 2) {
8541       CUR_STREAM (stream)->fps_n = stream->timescale;
8542       CUR_STREAM (stream)->fps_d = 1;
8543       fps_available = FALSE;
8544     } else {
8545       GstClockTime avg_duration;
8546       guint64 duration;
8547       guint32 n_samples;
8548
8549       /* duration and n_samples can be updated for fragmented format
8550        * so, framerate of fragmented format is calculated using data in a moof */
8551       if (qtdemux->fragmented && stream->n_samples_moof > 0
8552           && stream->duration_moof > 0) {
8553         n_samples = stream->n_samples_moof;
8554         duration = stream->duration_moof;
8555       } else {
8556         n_samples = stream->n_samples;
8557         duration = stream->duration;
8558       }
8559
8560       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8561       /* stream->duration is guint64, timescale, n_samples are guint32 */
8562       avg_duration =
8563           gst_util_uint64_scale_round (duration -
8564           first_duration, GST_SECOND,
8565           (guint64) (stream->timescale) * (n_samples - 1));
8566
8567       GST_LOG_OBJECT (qtdemux,
8568           "Calculating avg sample duration based on stream (or moof) duration %"
8569           G_GUINT64_FORMAT
8570           " minus first sample %u, leaving %d samples gives %"
8571           GST_TIME_FORMAT, duration, first_duration,
8572           n_samples - 1, GST_TIME_ARGS (avg_duration));
8573
8574       fps_available =
8575           gst_video_guess_framerate (avg_duration,
8576           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8577
8578       GST_DEBUG_OBJECT (qtdemux,
8579           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8580           stream->timescale, CUR_STREAM (stream)->fps_n,
8581           CUR_STREAM (stream)->fps_d);
8582     }
8583   }
8584
8585   return fps_available;
8586 }
8587
8588 static gboolean
8589 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8590 {
8591   if (stream->subtype == FOURCC_vide) {
8592     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8593
8594     if (CUR_STREAM (stream)->caps) {
8595       CUR_STREAM (stream)->caps =
8596           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8597
8598       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8599         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8600             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8601             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8602
8603       /* set framerate if calculated framerate is reliable */
8604       if (fps_available) {
8605         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8606             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8607             CUR_STREAM (stream)->fps_d, NULL);
8608       }
8609
8610       /* calculate pixel-aspect-ratio using display width and height */
8611       GST_DEBUG_OBJECT (qtdemux,
8612           "video size %dx%d, target display size %dx%d",
8613           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8614           stream->display_width, stream->display_height);
8615       /* qt file might have pasp atom */
8616       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8617         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8618             CUR_STREAM (stream)->par_h);
8619         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8620             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8621             CUR_STREAM (stream)->par_h, NULL);
8622       } else if (stream->display_width > 0 && stream->display_height > 0
8623           && CUR_STREAM (stream)->width > 0
8624           && CUR_STREAM (stream)->height > 0) {
8625         gint n, d;
8626
8627         /* calculate the pixel aspect ratio using the display and pixel w/h */
8628         n = stream->display_width * CUR_STREAM (stream)->height;
8629         d = stream->display_height * CUR_STREAM (stream)->width;
8630         if (n == d)
8631           n = d = 1;
8632         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8633         CUR_STREAM (stream)->par_w = n;
8634         CUR_STREAM (stream)->par_h = d;
8635         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8636             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8637             CUR_STREAM (stream)->par_h, NULL);
8638       }
8639
8640       if (CUR_STREAM (stream)->interlace_mode > 0) {
8641         if (CUR_STREAM (stream)->interlace_mode == 1) {
8642           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8643               G_TYPE_STRING, "progressive", NULL);
8644         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8645           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8646               G_TYPE_STRING, "interleaved", NULL);
8647           if (CUR_STREAM (stream)->field_order == 9) {
8648             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8649                 G_TYPE_STRING, "top-field-first", NULL);
8650           } else if (CUR_STREAM (stream)->field_order == 14) {
8651             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8652                 G_TYPE_STRING, "bottom-field-first", NULL);
8653           }
8654         }
8655       }
8656
8657       /* Create incomplete colorimetry here if needed */
8658       if (CUR_STREAM (stream)->colorimetry.range ||
8659           CUR_STREAM (stream)->colorimetry.matrix ||
8660           CUR_STREAM (stream)->colorimetry.transfer
8661           || CUR_STREAM (stream)->colorimetry.primaries) {
8662         gchar *colorimetry =
8663             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8664         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8665             G_TYPE_STRING, colorimetry, NULL);
8666         g_free (colorimetry);
8667       }
8668
8669       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8670         guint par_w = 1, par_h = 1;
8671
8672         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8673           par_w = CUR_STREAM (stream)->par_w;
8674           par_h = CUR_STREAM (stream)->par_h;
8675         }
8676
8677         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8678                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8679                 par_h)) {
8680           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8681         }
8682
8683         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8684             "multiview-mode", G_TYPE_STRING,
8685             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8686             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8687             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8688       }
8689     }
8690   }
8691
8692   else if (stream->subtype == FOURCC_soun) {
8693     if (CUR_STREAM (stream)->caps) {
8694       CUR_STREAM (stream)->caps =
8695           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8696       if (CUR_STREAM (stream)->rate > 0)
8697         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8698             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8699       if (CUR_STREAM (stream)->n_channels > 0)
8700         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8701             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8702       if (CUR_STREAM (stream)->n_channels > 2) {
8703         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8704          * correctly; this is just the minimum we can do - assume
8705          * we don't actually have any channel positions. */
8706         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8707             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8708       }
8709     }
8710   }
8711
8712   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8713     const GstStructure *s;
8714     QtDemuxStream *fps_stream = NULL;
8715     gboolean fps_available = FALSE;
8716
8717     /* CEA608 closed caption tracks are a bit special in that each sample
8718      * can contain CCs for multiple frames, and CCs can be omitted and have to
8719      * be inferred from the duration of the sample then.
8720      *
8721      * As such we take the framerate from the (first) video track here for
8722      * CEA608 as there must be one CC byte pair for every video frame
8723      * according to the spec.
8724      *
8725      * For CEA708 all is fine and there is one sample per frame.
8726      */
8727
8728     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8729     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8730       gint i;
8731
8732       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8733         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8734
8735         if (tmp->subtype == FOURCC_vide) {
8736           fps_stream = tmp;
8737           break;
8738         }
8739       }
8740
8741       if (fps_stream) {
8742         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8743         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8744         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8745       }
8746     } else {
8747       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8748       fps_stream = stream;
8749     }
8750
8751     CUR_STREAM (stream)->caps =
8752         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8753
8754     /* set framerate if calculated framerate is reliable */
8755     if (fps_available) {
8756       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8757           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8758           CUR_STREAM (stream)->fps_d, NULL);
8759     }
8760   }
8761
8762   if (stream->pad) {
8763     GstCaps *prev_caps = NULL;
8764
8765     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8766     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8767     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8768     gst_pad_set_active (stream->pad, TRUE);
8769
8770     gst_pad_use_fixed_caps (stream->pad);
8771
8772     if (stream->protected) {
8773       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8774         GST_ERROR_OBJECT (qtdemux,
8775             "Failed to configure protected stream caps.");
8776         return FALSE;
8777       }
8778     }
8779
8780     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8781         CUR_STREAM (stream)->caps);
8782     if (stream->new_stream) {
8783       GstEvent *event;
8784       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8785
8786       event =
8787           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8788           0);
8789       if (event) {
8790         gst_event_parse_stream_flags (event, &stream_flags);
8791         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8792           qtdemux->have_group_id = TRUE;
8793         else
8794           qtdemux->have_group_id = FALSE;
8795         gst_event_unref (event);
8796       } else if (!qtdemux->have_group_id) {
8797         qtdemux->have_group_id = TRUE;
8798         qtdemux->group_id = gst_util_group_id_next ();
8799       }
8800
8801       stream->new_stream = FALSE;
8802       event = gst_event_new_stream_start (stream->stream_id);
8803       if (qtdemux->have_group_id)
8804         gst_event_set_group_id (event, qtdemux->group_id);
8805       if (stream->disabled)
8806         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8807       if (CUR_STREAM (stream)->sparse) {
8808         stream_flags |= GST_STREAM_FLAG_SPARSE;
8809       } else {
8810         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8811       }
8812       gst_event_set_stream_flags (event, stream_flags);
8813       gst_pad_push_event (stream->pad, event);
8814     }
8815
8816     prev_caps = gst_pad_get_current_caps (stream->pad);
8817
8818     if (CUR_STREAM (stream)->caps) {
8819       if (!prev_caps
8820           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8821         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8822             CUR_STREAM (stream)->caps);
8823         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8824       } else {
8825         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8826       }
8827     } else {
8828       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8829     }
8830
8831     if (prev_caps)
8832       gst_caps_unref (prev_caps);
8833     stream->new_caps = FALSE;
8834   }
8835   return TRUE;
8836 }
8837
8838 static void
8839 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8840     QtDemuxStream * stream)
8841 {
8842   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8843     return;
8844
8845   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8846       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8847   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8848           stream->stsd_entries_length)) {
8849     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8850         (_("This file is invalid and cannot be played.")),
8851         ("New sample description id is out of bounds (%d >= %d)",
8852             stream->stsd_sample_description_id, stream->stsd_entries_length));
8853   } else {
8854     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8855     stream->new_caps = TRUE;
8856   }
8857 }
8858
8859 static gboolean
8860 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8861     QtDemuxStream * stream, GstTagList * list)
8862 {
8863   gboolean ret = TRUE;
8864
8865   if (stream->subtype == FOURCC_vide) {
8866     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8867
8868     stream->pad =
8869         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8870     g_free (name);
8871
8872     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8873       gst_object_unref (stream->pad);
8874       stream->pad = NULL;
8875       ret = FALSE;
8876       goto done;
8877     }
8878
8879     qtdemux->n_video_streams++;
8880   } else if (stream->subtype == FOURCC_soun) {
8881     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8882
8883     stream->pad =
8884         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8885     g_free (name);
8886     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8887       gst_object_unref (stream->pad);
8888       stream->pad = NULL;
8889       ret = FALSE;
8890       goto done;
8891     }
8892     qtdemux->n_audio_streams++;
8893   } else if (stream->subtype == FOURCC_strm) {
8894     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8895   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8896       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8897       || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
8898     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8899
8900     stream->pad =
8901         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8902     g_free (name);
8903     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8904       gst_object_unref (stream->pad);
8905       stream->pad = NULL;
8906       ret = FALSE;
8907       goto done;
8908     }
8909     qtdemux->n_sub_streams++;
8910   } else if (CUR_STREAM (stream)->caps) {
8911     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8912
8913     stream->pad =
8914         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8915     g_free (name);
8916     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8917       gst_object_unref (stream->pad);
8918       stream->pad = NULL;
8919       ret = FALSE;
8920       goto done;
8921     }
8922     qtdemux->n_video_streams++;
8923   } else {
8924     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8925     goto done;
8926   }
8927
8928   if (stream->pad) {
8929     GList *l;
8930
8931     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8932         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8933     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8934     GST_OBJECT_LOCK (qtdemux);
8935     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8936     GST_OBJECT_UNLOCK (qtdemux);
8937
8938     if (stream->stream_tags)
8939       gst_tag_list_unref (stream->stream_tags);
8940     stream->stream_tags = list;
8941     list = NULL;
8942     /* global tags go on each pad anyway */
8943     stream->send_global_tags = TRUE;
8944     /* send upstream GST_EVENT_PROTECTION events that were received before
8945        this source pad was created */
8946     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8947       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8948   }
8949 done:
8950   if (list)
8951     gst_tag_list_unref (list);
8952   return ret;
8953 }
8954
8955 /* find next atom with @fourcc starting at @offset */
8956 static GstFlowReturn
8957 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8958     guint64 * length, guint32 fourcc)
8959 {
8960   GstFlowReturn ret;
8961   guint32 lfourcc;
8962   GstBuffer *buf;
8963
8964   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8965       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8966
8967   while (TRUE) {
8968     GstMapInfo map;
8969
8970     buf = NULL;
8971     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8972     if (G_UNLIKELY (ret != GST_FLOW_OK))
8973       goto locate_failed;
8974     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8975       /* likely EOF */
8976       ret = GST_FLOW_EOS;
8977       gst_buffer_unref (buf);
8978       goto locate_failed;
8979     }
8980     gst_buffer_map (buf, &map, GST_MAP_READ);
8981     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8982     gst_buffer_unmap (buf, &map);
8983     gst_buffer_unref (buf);
8984
8985     if (G_UNLIKELY (*length == 0)) {
8986       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8987       ret = GST_FLOW_ERROR;
8988       goto locate_failed;
8989     }
8990
8991     if (lfourcc == fourcc) {
8992       GST_DEBUG_OBJECT (qtdemux, "found '%" GST_FOURCC_FORMAT " at offset %"
8993           G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8994       break;
8995     } else {
8996       GST_LOG_OBJECT (qtdemux,
8997           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8998           GST_FOURCC_ARGS (lfourcc), *offset);
8999       if (*offset == G_MAXUINT64)
9000         goto locate_failed;
9001       *offset += *length;
9002     }
9003   }
9004
9005   return GST_FLOW_OK;
9006
9007 locate_failed:
9008   {
9009     /* might simply have had last one */
9010     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
9011     return ret;
9012   }
9013 }
9014
9015 /* should only do something in pull mode */
9016 /* call with OBJECT lock */
9017 static GstFlowReturn
9018 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
9019 {
9020   guint64 length, offset;
9021   GstBuffer *buf = NULL;
9022   GstFlowReturn ret = GST_FLOW_OK;
9023   GstFlowReturn res = GST_FLOW_OK;
9024   GstMapInfo map;
9025
9026   offset = qtdemux->moof_offset;
9027   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
9028
9029   if (!offset) {
9030     GST_DEBUG_OBJECT (qtdemux, "no next moof");
9031     return GST_FLOW_EOS;
9032   }
9033
9034   /* best not do pull etc with lock held */
9035   GST_OBJECT_UNLOCK (qtdemux);
9036
9037   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9038   if (ret != GST_FLOW_OK)
9039     goto flow_failed;
9040
9041   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
9042   if (G_UNLIKELY (ret != GST_FLOW_OK))
9043     goto flow_failed;
9044   gst_buffer_map (buf, &map, GST_MAP_READ);
9045   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
9046     gst_buffer_unmap (buf, &map);
9047     gst_buffer_unref (buf);
9048     buf = NULL;
9049     goto parse_failed;
9050   }
9051
9052   gst_buffer_unmap (buf, &map);
9053   gst_buffer_unref (buf);
9054   buf = NULL;
9055
9056   offset += length;
9057   /* look for next moof */
9058   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9059   if (G_UNLIKELY (ret != GST_FLOW_OK))
9060     goto flow_failed;
9061
9062 exit:
9063   GST_OBJECT_LOCK (qtdemux);
9064
9065   qtdemux->moof_offset = offset;
9066
9067   return res;
9068
9069 parse_failed:
9070   {
9071     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9072     offset = 0;
9073     res = GST_FLOW_ERROR;
9074     goto exit;
9075   }
9076 flow_failed:
9077   {
9078     /* maybe upstream temporarily flushing */
9079     if (ret != GST_FLOW_FLUSHING) {
9080       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9081       offset = 0;
9082     } else {
9083       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9084       /* resume at current position next time */
9085     }
9086     res = ret;
9087     goto exit;
9088   }
9089 }
9090
9091 static void
9092 qtdemux_merge_sample_table (GstQTDemux * qtdemux, QtDemuxStream * stream)
9093 {
9094   guint i;
9095   guint32 num_chunks;
9096   gint32 stts_duration;
9097   GstByteWriter stsc, stts, stsz;
9098
9099   /* Each sample has a different size, which we don't support for merging */
9100   if (stream->sample_size == 0) {
9101     GST_DEBUG_OBJECT (qtdemux,
9102         "Not all samples have the same size, not merging");
9103     return;
9104   }
9105
9106   /* The stream has a ctts table, we don't support that */
9107   if (stream->ctts_present) {
9108     GST_DEBUG_OBJECT (qtdemux, "Have ctts, not merging");
9109     return;
9110   }
9111
9112   /* If there's a sync sample table also ignore this stream */
9113   if (stream->stps_present || stream->stss_present) {
9114     GST_DEBUG_OBJECT (qtdemux, "Have stss/stps, not merging");
9115     return;
9116   }
9117
9118   /* If chunks are considered samples already ignore this stream */
9119   if (stream->chunks_are_samples) {
9120     GST_DEBUG_OBJECT (qtdemux, "Chunks are samples, not merging");
9121     return;
9122   }
9123
9124   /* Require that all samples have the same duration */
9125   if (stream->n_sample_times > 1) {
9126     GST_DEBUG_OBJECT (qtdemux, "Not all samples have the same duration");
9127     return;
9128   }
9129
9130   /* Parse the stts to get the sample duration and number of samples */
9131   gst_byte_reader_skip_unchecked (&stream->stts, 4);
9132   stts_duration = gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9133
9134   /* Parse the number of chunks from the stco manually because the
9135    * reader is already behind that */
9136   num_chunks = GST_READ_UINT32_BE (stream->stco.data + 4);
9137
9138   GST_DEBUG_OBJECT (qtdemux, "sample_duration %d, num_chunks %u", stts_duration,
9139       num_chunks);
9140
9141   /* Now parse stsc, convert chunks into single samples and generate a
9142    * new stsc, stts and stsz from this information */
9143   gst_byte_writer_init (&stsc);
9144   gst_byte_writer_init (&stts);
9145   gst_byte_writer_init (&stsz);
9146
9147   /* Note: we skip fourccs, size, version, flags and other fields of the new
9148    * atoms as the byte readers with them are already behind that position
9149    * anyway and only update the values of those inside the stream directly.
9150    */
9151   stream->n_sample_times = 0;
9152   stream->n_samples = 0;
9153   for (i = 0; i < stream->n_samples_per_chunk; i++) {
9154     guint j;
9155     guint32 first_chunk, last_chunk, samples_per_chunk, sample_description_id;
9156
9157     first_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9158     samples_per_chunk = gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9159     sample_description_id =
9160         gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9161
9162     if (i == stream->n_samples_per_chunk - 1) {
9163       /* +1 because first_chunk is 1-based */
9164       last_chunk = num_chunks + 1;
9165     } else {
9166       last_chunk = gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9167     }
9168
9169     GST_DEBUG_OBJECT (qtdemux,
9170         "Merging first_chunk: %u, last_chunk: %u, samples_per_chunk: %u, sample_description_id: %u",
9171         first_chunk, last_chunk, samples_per_chunk, sample_description_id);
9172
9173     gst_byte_writer_put_uint32_be (&stsc, first_chunk);
9174     /* One sample in this chunk */
9175     gst_byte_writer_put_uint32_be (&stsc, 1);
9176     gst_byte_writer_put_uint32_be (&stsc, sample_description_id);
9177
9178     /* For each chunk write a stts and stsz entry now */
9179     gst_byte_writer_put_uint32_be (&stts, last_chunk - first_chunk);
9180     gst_byte_writer_put_uint32_be (&stts, stts_duration * samples_per_chunk);
9181     for (j = first_chunk; j < last_chunk; j++) {
9182       gst_byte_writer_put_uint32_be (&stsz,
9183           stream->sample_size * samples_per_chunk);
9184     }
9185
9186     stream->n_sample_times += 1;
9187     stream->n_samples += last_chunk - first_chunk;
9188   }
9189
9190   g_assert_cmpint (stream->n_samples, ==, num_chunks);
9191
9192   GST_DEBUG_OBJECT (qtdemux, "Have %u samples and %u sample times",
9193       stream->n_samples, stream->n_sample_times);
9194
9195   /* We don't have a fixed sample size anymore */
9196   stream->sample_size = 0;
9197
9198   /* Free old data for the atoms */
9199   g_free ((gpointer) stream->stsz.data);
9200   stream->stsz.data = NULL;
9201   g_free ((gpointer) stream->stsc.data);
9202   stream->stsc.data = NULL;
9203   g_free ((gpointer) stream->stts.data);
9204   stream->stts.data = NULL;
9205
9206   /* Store new data and replace byte readers */
9207   stream->stsz.size = gst_byte_writer_get_size (&stsz);
9208   stream->stsz.data = gst_byte_writer_reset_and_get_data (&stsz);
9209   gst_byte_reader_init (&stream->stsz, stream->stsz.data, stream->stsz.size);
9210   stream->stts.size = gst_byte_writer_get_size (&stts);
9211   stream->stts.data = gst_byte_writer_reset_and_get_data (&stts);
9212   gst_byte_reader_init (&stream->stts, stream->stts.data, stream->stts.size);
9213   stream->stsc.size = gst_byte_writer_get_size (&stsc);
9214   stream->stsc.data = gst_byte_writer_reset_and_get_data (&stsc);
9215   gst_byte_reader_init (&stream->stsc, stream->stsc.data, stream->stsc.size);
9216 }
9217
9218 /* initialise bytereaders for stbl sub-atoms */
9219 static gboolean
9220 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9221 {
9222   stream->stbl_index = -1;      /* no samples have yet been parsed */
9223   stream->sample_index = -1;
9224
9225   /* time-to-sample atom */
9226   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9227     goto corrupt_file;
9228
9229   /* copy atom data into a new buffer for later use */
9230   stream->stts.data = g_memdup2 (stream->stts.data, stream->stts.size);
9231
9232   /* skip version + flags */
9233   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9234       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9235     goto corrupt_file;
9236   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9237
9238   /* make sure there's enough data */
9239   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9240     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9241     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9242         stream->n_sample_times);
9243     if (!stream->n_sample_times)
9244       goto corrupt_file;
9245   }
9246
9247   /* sync sample atom */
9248   stream->stps_present = FALSE;
9249   if ((stream->stss_present =
9250           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9251               &stream->stss) ? TRUE : FALSE) == TRUE) {
9252     /* copy atom data into a new buffer for later use */
9253     stream->stss.data = g_memdup2 (stream->stss.data, stream->stss.size);
9254
9255     /* skip version + flags */
9256     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9257         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9258       goto corrupt_file;
9259
9260     if (stream->n_sample_syncs) {
9261       /* make sure there's enough data */
9262       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9263         goto corrupt_file;
9264     }
9265
9266     /* partial sync sample atom */
9267     if ((stream->stps_present =
9268             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9269                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9270       /* copy atom data into a new buffer for later use */
9271       stream->stps.data = g_memdup2 (stream->stps.data, stream->stps.size);
9272
9273       /* skip version + flags */
9274       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9275           !gst_byte_reader_get_uint32_be (&stream->stps,
9276               &stream->n_sample_partial_syncs))
9277         goto corrupt_file;
9278
9279       /* if there are no entries, the stss table contains the real
9280        * sync samples */
9281       if (stream->n_sample_partial_syncs) {
9282         /* make sure there's enough data */
9283         if (!qt_atom_parser_has_chunks (&stream->stps,
9284                 stream->n_sample_partial_syncs, 4))
9285           goto corrupt_file;
9286       }
9287     }
9288   }
9289
9290   /* sample size */
9291   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9292     goto no_samples;
9293
9294   /* copy atom data into a new buffer for later use */
9295   stream->stsz.data = g_memdup2 (stream->stsz.data, stream->stsz.size);
9296
9297   /* skip version + flags */
9298   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9299       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9300     goto corrupt_file;
9301
9302   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9303     goto corrupt_file;
9304
9305   if (!stream->n_samples)
9306     goto no_samples;
9307
9308   /* sample-to-chunk atom */
9309   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9310     goto corrupt_file;
9311
9312   /* copy atom data into a new buffer for later use */
9313   stream->stsc.data = g_memdup2 (stream->stsc.data, stream->stsc.size);
9314
9315   /* skip version + flags */
9316   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9317       !gst_byte_reader_get_uint32_be (&stream->stsc,
9318           &stream->n_samples_per_chunk))
9319     goto corrupt_file;
9320
9321   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9322       stream->n_samples_per_chunk);
9323
9324   /* make sure there's enough data */
9325   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9326           12))
9327     goto corrupt_file;
9328
9329
9330   /* chunk offset */
9331   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9332     stream->co_size = sizeof (guint32);
9333   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9334           &stream->stco))
9335     stream->co_size = sizeof (guint64);
9336   else
9337     goto corrupt_file;
9338
9339   /* copy atom data into a new buffer for later use */
9340   stream->stco.data = g_memdup2 (stream->stco.data, stream->stco.size);
9341
9342   /* skip version + flags */
9343   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9344     goto corrupt_file;
9345
9346   /* chunks_are_samples == TRUE means treat chunks as samples */
9347   stream->chunks_are_samples = stream->sample_size
9348       && !CUR_STREAM (stream)->sampled;
9349   if (stream->chunks_are_samples) {
9350     /* treat chunks as samples */
9351     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9352       goto corrupt_file;
9353   } else {
9354     /* skip number of entries */
9355     if (!gst_byte_reader_skip (&stream->stco, 4))
9356       goto corrupt_file;
9357
9358     /* make sure there are enough data in the stsz atom */
9359     if (!stream->sample_size) {
9360       /* different sizes for each sample */
9361       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9362         goto corrupt_file;
9363     }
9364   }
9365
9366   /* composition time-to-sample */
9367   if ((stream->ctts_present =
9368           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9369               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9370     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9371
9372     /* copy atom data into a new buffer for later use */
9373     stream->ctts.data = g_memdup2 (stream->ctts.data, stream->ctts.size);
9374
9375     /* skip version + flags */
9376     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9377         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9378             &stream->n_composition_times))
9379       goto corrupt_file;
9380
9381     /* make sure there's enough data */
9382     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9383             4 + 4))
9384       goto corrupt_file;
9385
9386     /* This is optional, if missing we iterate the ctts */
9387     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9388       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9389           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift))
9390         goto corrupt_file;
9391     } else {
9392       gint32 cslg_least = 0;
9393       guint num_entries, pos;
9394       gint i;
9395
9396       pos = gst_byte_reader_get_pos (&stream->ctts);
9397       num_entries = stream->n_composition_times;
9398
9399       stream->cslg_shift = 0;
9400
9401       for (i = 0; i < num_entries; i++) {
9402         gint32 offset;
9403
9404         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9405         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9406         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9407          * slightly inaccurate PTS could be more usable than corrupted one */
9408         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9409           GST_WARNING_OBJECT (qtdemux,
9410               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9411               " larger than duration %" G_GUINT64_FORMAT,
9412               offset, stream->duration);
9413
9414           stream->cslg_shift = 0;
9415           stream->ctts_present = FALSE;
9416           goto done;
9417         }
9418
9419         if (offset < cslg_least)
9420           cslg_least = offset;
9421       }
9422
9423       if (cslg_least < 0)
9424         stream->cslg_shift = ABS (cslg_least);
9425       else
9426         stream->cslg_shift = 0;
9427
9428       /* reset the reader so we can generate sample table */
9429       gst_byte_reader_set_pos (&stream->ctts, pos);
9430     }
9431   } else {
9432     /* Ensure the cslg_shift value is consistent so we can use it
9433      * unconditionally to produce TS and Segment */
9434     stream->cslg_shift = 0;
9435   }
9436
9437   /* For raw audio streams especially we might want to merge the samples
9438    * to not output one audio sample per buffer. We're doing this here
9439    * before allocating the sample tables so that from this point onwards
9440    * the number of container samples are static */
9441   if (stream->min_buffer_size > 0) {
9442     qtdemux_merge_sample_table (qtdemux, stream);
9443   }
9444
9445 done:
9446   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9447       stream->n_samples, (guint) sizeof (QtDemuxSample),
9448       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9449
9450   if (stream->n_samples >=
9451       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9452     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9453         "be larger than %uMB (broken file?)", stream->n_samples,
9454         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9455     return FALSE;
9456   }
9457
9458   g_assert (stream->samples == NULL);
9459   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9460   if (!stream->samples) {
9461     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9462         stream->n_samples);
9463     return FALSE;
9464   }
9465
9466   return TRUE;
9467
9468 corrupt_file:
9469   {
9470     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9471         (_("This file is corrupt and cannot be played.")), (NULL));
9472     return FALSE;
9473   }
9474 no_samples:
9475   {
9476     gst_qtdemux_stbl_free (stream);
9477     if (!qtdemux->fragmented) {
9478       /* not quite good */
9479       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9480       return FALSE;
9481     } else {
9482       /* may pick up samples elsewhere */
9483       return TRUE;
9484     }
9485   }
9486 }
9487
9488 /* collect samples from the next sample to be parsed up to sample @n for @stream
9489  * by reading the info from @stbl
9490  *
9491  * This code can be executed from both the streaming thread and the seeking
9492  * thread so it takes the object lock to protect itself
9493  */
9494 static gboolean
9495 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9496 {
9497   gint i, j, k;
9498   QtDemuxSample *samples, *first, *cur, *last;
9499   guint32 n_samples_per_chunk;
9500   guint32 n_samples;
9501
9502   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9503       GST_FOURCC_FORMAT ", pad %s",
9504       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9505       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9506
9507   n_samples = stream->n_samples;
9508
9509   if (n >= n_samples)
9510     goto out_of_samples;
9511
9512   GST_OBJECT_LOCK (qtdemux);
9513   if (n <= stream->stbl_index)
9514     goto already_parsed;
9515
9516   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9517
9518   if (!stream->stsz.data) {
9519     /* so we already parsed and passed all the moov samples;
9520      * onto fragmented ones */
9521     g_assert (qtdemux->fragmented);
9522     goto done;
9523   }
9524
9525   /* pointer to the sample table */
9526   samples = stream->samples;
9527
9528   /* starts from -1, moves to the next sample index to parse */
9529   stream->stbl_index++;
9530
9531   /* keep track of the first and last sample to fill */
9532   first = &samples[stream->stbl_index];
9533   last = &samples[n];
9534
9535   if (!stream->chunks_are_samples) {
9536     /* set the sample sizes */
9537     if (stream->sample_size == 0) {
9538       /* different sizes for each sample */
9539       for (cur = first; cur <= last; cur++) {
9540         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9541         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9542             (guint) (cur - samples), cur->size);
9543       }
9544     } else {
9545       /* samples have the same size */
9546       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9547       for (cur = first; cur <= last; cur++)
9548         cur->size = stream->sample_size;
9549     }
9550   }
9551
9552   n_samples_per_chunk = stream->n_samples_per_chunk;
9553   cur = first;
9554
9555   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9556     guint32 last_chunk;
9557
9558     if (stream->stsc_chunk_index >= stream->last_chunk
9559         || stream->stsc_chunk_index < stream->first_chunk) {
9560       stream->first_chunk =
9561           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9562       stream->samples_per_chunk =
9563           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9564       /* starts from 1 */
9565       stream->stsd_sample_description_id =
9566           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9567
9568       /* chunk numbers are counted from 1 it seems */
9569       if (G_UNLIKELY (stream->first_chunk == 0))
9570         goto corrupt_file;
9571
9572       --stream->first_chunk;
9573
9574       /* the last chunk of each entry is calculated by taking the first chunk
9575        * of the next entry; except if there is no next, where we fake it with
9576        * INT_MAX */
9577       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9578         stream->last_chunk = G_MAXUINT32;
9579       } else {
9580         stream->last_chunk =
9581             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9582         if (G_UNLIKELY (stream->last_chunk == 0))
9583           goto corrupt_file;
9584
9585         --stream->last_chunk;
9586       }
9587
9588       GST_LOG_OBJECT (qtdemux,
9589           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9590           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9591           stream->samples_per_chunk, stream->stsd_sample_description_id);
9592
9593       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9594         goto corrupt_file;
9595
9596       if (stream->last_chunk != G_MAXUINT32) {
9597         if (!qt_atom_parser_peek_sub (&stream->stco,
9598                 stream->first_chunk * stream->co_size,
9599                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9600                 &stream->co_chunk))
9601           goto corrupt_file;
9602
9603       } else {
9604         stream->co_chunk = stream->stco;
9605         if (!gst_byte_reader_skip (&stream->co_chunk,
9606                 stream->first_chunk * stream->co_size))
9607           goto corrupt_file;
9608       }
9609
9610       stream->stsc_chunk_index = stream->first_chunk;
9611     }
9612
9613     last_chunk = stream->last_chunk;
9614
9615     if (stream->chunks_are_samples) {
9616       cur = &samples[stream->stsc_chunk_index];
9617
9618       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9619         if (j > n) {
9620           /* save state */
9621           stream->stsc_chunk_index = j;
9622           goto done;
9623         }
9624
9625         cur->offset =
9626             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9627             stream->co_size);
9628
9629         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9630             "%" G_GUINT64_FORMAT, j, cur->offset);
9631
9632         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9633             CUR_STREAM (stream)->bytes_per_frame > 0) {
9634           cur->size =
9635               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9636               CUR_STREAM (stream)->samples_per_frame *
9637               CUR_STREAM (stream)->bytes_per_frame;
9638         } else {
9639           cur->size = stream->samples_per_chunk;
9640         }
9641
9642         GST_DEBUG_OBJECT (qtdemux,
9643             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9644             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9645                     stream->stco_sample_index)), cur->size);
9646
9647         cur->timestamp = stream->stco_sample_index;
9648         cur->duration = stream->samples_per_chunk;
9649         cur->keyframe = TRUE;
9650         cur++;
9651
9652         stream->stco_sample_index += stream->samples_per_chunk;
9653       }
9654       stream->stsc_chunk_index = j;
9655     } else {
9656       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9657         guint32 samples_per_chunk;
9658         guint64 chunk_offset;
9659
9660         if (!stream->stsc_sample_index
9661             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9662                 &stream->chunk_offset))
9663           goto corrupt_file;
9664
9665         samples_per_chunk = stream->samples_per_chunk;
9666         chunk_offset = stream->chunk_offset;
9667
9668         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9669           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9670               G_GUINT64_FORMAT " and size %d",
9671               (guint) (cur - samples), chunk_offset, cur->size);
9672
9673           cur->offset = chunk_offset;
9674           chunk_offset += cur->size;
9675           cur++;
9676
9677           if (G_UNLIKELY (cur > last)) {
9678             /* save state */
9679             stream->stsc_sample_index = k + 1;
9680             stream->chunk_offset = chunk_offset;
9681             stream->stsc_chunk_index = j;
9682             goto done2;
9683           }
9684         }
9685         stream->stsc_sample_index = 0;
9686       }
9687       stream->stsc_chunk_index = j;
9688     }
9689     stream->stsc_index++;
9690   }
9691
9692   if (stream->chunks_are_samples)
9693     goto ctts;
9694 done2:
9695   {
9696     guint32 n_sample_times;
9697
9698     n_sample_times = stream->n_sample_times;
9699     cur = first;
9700
9701     for (i = stream->stts_index; i < n_sample_times; i++) {
9702       guint32 stts_samples;
9703       gint32 stts_duration;
9704       gint64 stts_time;
9705
9706       if (stream->stts_sample_index >= stream->stts_samples
9707           || !stream->stts_sample_index) {
9708
9709         stream->stts_samples =
9710             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9711         stream->stts_duration =
9712             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9713
9714         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9715             i, stream->stts_samples, stream->stts_duration);
9716
9717         stream->stts_sample_index = 0;
9718       }
9719
9720       stts_samples = stream->stts_samples;
9721       stts_duration = stream->stts_duration;
9722       stts_time = stream->stts_time;
9723
9724       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9725         GST_DEBUG_OBJECT (qtdemux,
9726             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9727             (guint) (cur - samples), j,
9728             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9729
9730         cur->timestamp = stts_time;
9731         cur->duration = stts_duration;
9732
9733         /* avoid 32-bit wrap-around,
9734          * but still mind possible 'negative' duration */
9735         stts_time += (gint64) stts_duration;
9736         cur++;
9737
9738         if (G_UNLIKELY (cur > last)) {
9739           /* save values */
9740           stream->stts_time = stts_time;
9741           stream->stts_sample_index = j + 1;
9742           if (stream->stts_sample_index >= stream->stts_samples)
9743             stream->stts_index++;
9744           goto done3;
9745         }
9746       }
9747       stream->stts_sample_index = 0;
9748       stream->stts_time = stts_time;
9749       stream->stts_index++;
9750     }
9751     /* fill up empty timestamps with the last timestamp, this can happen when
9752      * the last samples do not decode and so we don't have timestamps for them.
9753      * We however look at the last timestamp to estimate the track length so we
9754      * need something in here. */
9755     for (; cur < last; cur++) {
9756       GST_DEBUG_OBJECT (qtdemux,
9757           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9758           (guint) (cur - samples),
9759           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9760       cur->timestamp = stream->stts_time;
9761       cur->duration = -1;
9762     }
9763   }
9764 done3:
9765   {
9766     /* sample sync, can be NULL */
9767     if (stream->stss_present == TRUE) {
9768       guint32 n_sample_syncs;
9769
9770       n_sample_syncs = stream->n_sample_syncs;
9771
9772       if (!n_sample_syncs) {
9773         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9774         stream->all_keyframe = TRUE;
9775       } else {
9776         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9777           /* note that the first sample is index 1, not 0 */
9778           guint32 index;
9779
9780           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9781
9782           if (G_LIKELY (index > 0 && index <= n_samples)) {
9783             index -= 1;
9784             samples[index].keyframe = TRUE;
9785             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9786             /* and exit if we have enough samples */
9787             if (G_UNLIKELY (index >= n)) {
9788               i++;
9789               break;
9790             }
9791           }
9792         }
9793         /* save state */
9794         stream->stss_index = i;
9795       }
9796
9797       /* stps marks partial sync frames like open GOP I-Frames */
9798       if (stream->stps_present == TRUE) {
9799         guint32 n_sample_partial_syncs;
9800
9801         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9802
9803         /* if there are no entries, the stss table contains the real
9804          * sync samples */
9805         if (n_sample_partial_syncs) {
9806           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9807             /* note that the first sample is index 1, not 0 */
9808             guint32 index;
9809
9810             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9811
9812             if (G_LIKELY (index > 0 && index <= n_samples)) {
9813               index -= 1;
9814               samples[index].keyframe = TRUE;
9815               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9816               /* and exit if we have enough samples */
9817               if (G_UNLIKELY (index >= n)) {
9818                 i++;
9819                 break;
9820               }
9821             }
9822           }
9823           /* save state */
9824           stream->stps_index = i;
9825         }
9826       }
9827     } else {
9828       /* no stss, all samples are keyframes */
9829       stream->all_keyframe = TRUE;
9830       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9831     }
9832   }
9833
9834 ctts:
9835   /* composition time to sample */
9836   if (stream->ctts_present == TRUE) {
9837     guint32 n_composition_times;
9838     guint32 ctts_count;
9839     gint32 ctts_soffset;
9840
9841     /* Fill in the pts_offsets */
9842     cur = first;
9843     n_composition_times = stream->n_composition_times;
9844
9845     for (i = stream->ctts_index; i < n_composition_times; i++) {
9846       if (stream->ctts_sample_index >= stream->ctts_count
9847           || !stream->ctts_sample_index) {
9848         stream->ctts_count =
9849             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9850         stream->ctts_soffset =
9851             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9852         stream->ctts_sample_index = 0;
9853       }
9854
9855       ctts_count = stream->ctts_count;
9856       ctts_soffset = stream->ctts_soffset;
9857
9858       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9859         cur->pts_offset = ctts_soffset;
9860         cur++;
9861
9862         if (G_UNLIKELY (cur > last)) {
9863           /* save state */
9864           stream->ctts_sample_index = j + 1;
9865           goto done;
9866         }
9867       }
9868       stream->ctts_sample_index = 0;
9869       stream->ctts_index++;
9870     }
9871   }
9872 done:
9873   stream->stbl_index = n;
9874   /* if index has been completely parsed, free data that is no-longer needed */
9875   if (n + 1 == stream->n_samples) {
9876     gst_qtdemux_stbl_free (stream);
9877     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9878     if (qtdemux->pullbased) {
9879       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9880       while (n + 1 == stream->n_samples)
9881         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9882           break;
9883     }
9884   }
9885   GST_OBJECT_UNLOCK (qtdemux);
9886
9887   return TRUE;
9888
9889   /* SUCCESS */
9890 already_parsed:
9891   {
9892     GST_LOG_OBJECT (qtdemux,
9893         "Tried to parse up to sample %u but this sample has already been parsed",
9894         n);
9895     /* if fragmented, there may be more */
9896     if (qtdemux->fragmented && n == stream->stbl_index)
9897       goto done;
9898     GST_OBJECT_UNLOCK (qtdemux);
9899     return TRUE;
9900   }
9901   /* ERRORS */
9902 out_of_samples:
9903   {
9904     GST_LOG_OBJECT (qtdemux,
9905         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9906         stream->n_samples);
9907     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9908         (_("This file is corrupt and cannot be played.")), (NULL));
9909     return FALSE;
9910   }
9911 corrupt_file:
9912   {
9913     GST_OBJECT_UNLOCK (qtdemux);
9914     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9915         (_("This file is corrupt and cannot be played.")), (NULL));
9916     return FALSE;
9917   }
9918 }
9919
9920 /* collect all segment info for @stream.
9921  */
9922 static gboolean
9923 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9924     GNode * trak)
9925 {
9926   GNode *edts;
9927   /* accept edts if they contain gaps at start and there is only
9928    * one media segment */
9929   gboolean allow_pushbased_edts = TRUE;
9930   gint media_segments_count = 0;
9931
9932   /* parse and prepare segment info from the edit list */
9933   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9934   stream->n_segments = 0;
9935   stream->segments = NULL;
9936   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9937     GNode *elst;
9938     gint n_segments;
9939     gint segment_number, entry_size;
9940     guint64 time;
9941     GstClockTime stime;
9942     const guint8 *buffer;
9943     guint8 version;
9944     guint32 size;
9945
9946     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9947     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9948       goto done;
9949
9950     buffer = elst->data;
9951
9952     size = QT_UINT32 (buffer);
9953     /* version, flags, n_segments */
9954     if (size < 16) {
9955       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9956       goto done;
9957     }
9958     version = QT_UINT8 (buffer + 8);
9959     entry_size = (version == 1) ? 20 : 12;
9960
9961     n_segments = QT_UINT32 (buffer + 12);
9962
9963     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9964       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9965       goto done;
9966     }
9967
9968     /* we might allocate a bit too much, at least allocate 1 segment */
9969     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9970
9971     /* segments always start from 0 */
9972     time = 0;
9973     stime = 0;
9974     buffer += 16;
9975     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9976       guint64 duration;
9977       guint64 media_time;
9978       gboolean empty_edit = FALSE;
9979       QtDemuxSegment *segment;
9980       guint32 rate_int;
9981       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9982
9983       if (version == 1) {
9984         media_time = QT_UINT64 (buffer + 8);
9985         duration = QT_UINT64 (buffer);
9986         if (media_time == G_MAXUINT64)
9987           empty_edit = TRUE;
9988       } else {
9989         media_time = QT_UINT32 (buffer + 4);
9990         duration = QT_UINT32 (buffer);
9991         if (media_time == G_MAXUINT32)
9992           empty_edit = TRUE;
9993       }
9994
9995       if (!empty_edit)
9996         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9997
9998       segment = &stream->segments[segment_number];
9999
10000       /* time and duration expressed in global timescale */
10001       segment->time = stime;
10002       if (duration != 0 || empty_edit) {
10003         /* edge case: empty edits with duration=zero are treated here.
10004          * (files should not have these anyway). */
10005
10006         /* add non scaled values so we don't cause roundoff errors */
10007         time += duration;
10008         stime = QTTIME_TO_GSTTIME (qtdemux, time);
10009         segment->duration = stime - segment->time;
10010       } else {
10011         /* zero duration does not imply media_start == media_stop
10012          * but, only specify media_start. The edit ends with the track. */
10013         stime = segment->duration = GST_CLOCK_TIME_NONE;
10014         /* Don't allow more edits after this one. */
10015         n_segments = segment_number + 1;
10016       }
10017       segment->stop_time = stime;
10018
10019       segment->trak_media_start = media_time;
10020       /* media_time expressed in stream timescale */
10021       if (!empty_edit) {
10022         segment->media_start = media_start;
10023         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
10024             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
10025         media_segments_count++;
10026       } else {
10027         segment->media_start = GST_CLOCK_TIME_NONE;
10028         segment->media_stop = GST_CLOCK_TIME_NONE;
10029       }
10030       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
10031
10032       if (rate_int <= 1) {
10033         /* 0 is not allowed, some programs write 1 instead of the floating point
10034          * value */
10035         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
10036             rate_int);
10037         segment->rate = 1;
10038       } else {
10039         segment->rate = rate_int / 65536.0;
10040       }
10041
10042       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
10043           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
10044           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
10045           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
10046           segment_number, GST_TIME_ARGS (segment->time),
10047           GST_TIME_ARGS (segment->duration),
10048           GST_TIME_ARGS (segment->media_start), media_time,
10049           GST_TIME_ARGS (segment->media_stop),
10050           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
10051           stream->timescale);
10052       if (segment->stop_time > qtdemux->segment.stop &&
10053           !qtdemux->upstream_format_is_time) {
10054         GST_WARNING_OBJECT (qtdemux, "Segment %d "
10055             " extends to %" GST_TIME_FORMAT
10056             " past the end of the declared movie duration %" GST_TIME_FORMAT
10057             " movie segment will be extended", segment_number,
10058             GST_TIME_ARGS (segment->stop_time),
10059             GST_TIME_ARGS (qtdemux->segment.stop));
10060         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
10061       }
10062
10063       buffer += entry_size;
10064     }
10065     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
10066     stream->n_segments = n_segments;
10067     if (media_segments_count != 1)
10068       allow_pushbased_edts = FALSE;
10069   }
10070 done:
10071
10072   /* push based does not handle segments, so act accordingly here,
10073    * and warn if applicable */
10074   if (!qtdemux->pullbased && !allow_pushbased_edts) {
10075     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
10076     /* remove and use default one below, we stream like it anyway */
10077     g_free (stream->segments);
10078     stream->segments = NULL;
10079     stream->n_segments = 0;
10080   }
10081
10082   /* no segments, create one to play the complete trak */
10083   if (stream->n_segments == 0) {
10084     GstClockTime stream_duration =
10085         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
10086
10087     if (stream->segments == NULL)
10088       stream->segments = g_new (QtDemuxSegment, 1);
10089
10090     /* represent unknown our way */
10091     if (stream_duration == 0)
10092       stream_duration = GST_CLOCK_TIME_NONE;
10093
10094     stream->segments[0].time = 0;
10095     stream->segments[0].stop_time = stream_duration;
10096     stream->segments[0].duration = stream_duration;
10097     stream->segments[0].media_start = 0;
10098     stream->segments[0].media_stop = stream_duration;
10099     stream->segments[0].rate = 1.0;
10100     stream->segments[0].trak_media_start = 0;
10101
10102     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
10103         GST_TIME_ARGS (stream_duration));
10104     stream->n_segments = 1;
10105     stream->dummy_segment = TRUE;
10106   }
10107   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
10108
10109   return TRUE;
10110 }
10111
10112 /*
10113  * Parses the stsd atom of a svq3 trak looking for
10114  * the SMI and gama atoms.
10115  */
10116 static void
10117 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
10118     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
10119 {
10120   const guint8 *_gamma = NULL;
10121   GstBuffer *_seqh = NULL;
10122   const guint8 *stsd_data = stsd_entry_data;
10123   guint32 length = QT_UINT32 (stsd_data);
10124   guint16 version;
10125
10126   if (length < 32) {
10127     GST_WARNING_OBJECT (qtdemux, "stsd too short");
10128     goto end;
10129   }
10130
10131   stsd_data += 16;
10132   length -= 16;
10133   version = QT_UINT16 (stsd_data);
10134   if (version == 3) {
10135     if (length >= 70) {
10136       length -= 70;
10137       stsd_data += 70;
10138       while (length > 8) {
10139         guint32 fourcc, size;
10140         const guint8 *data;
10141         size = QT_UINT32 (stsd_data);
10142         fourcc = QT_FOURCC (stsd_data + 4);
10143         data = stsd_data + 8;
10144
10145         if (size == 0) {
10146           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
10147               "svq3 atom parsing");
10148           goto end;
10149         }
10150
10151         switch (fourcc) {
10152           case FOURCC_gama:{
10153             if (size == 12) {
10154               _gamma = data;
10155             } else {
10156               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
10157                   " for gama atom, expected 12", size);
10158             }
10159             break;
10160           }
10161           case FOURCC_SMI_:{
10162             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
10163               guint32 seqh_size;
10164               if (_seqh != NULL) {
10165                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
10166                     " found, ignoring");
10167               } else {
10168                 seqh_size = QT_UINT32 (data + 4);
10169                 if (seqh_size > 0) {
10170                   _seqh = gst_buffer_new_and_alloc (seqh_size);
10171                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
10172                 }
10173               }
10174             }
10175             break;
10176           }
10177           default:{
10178             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
10179                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
10180           }
10181         }
10182
10183         if (size <= length) {
10184           length -= size;
10185           stsd_data += size;
10186         }
10187       }
10188     } else {
10189       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10190     }
10191   } else {
10192     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10193         G_GUINT16_FORMAT, version);
10194     goto end;
10195   }
10196
10197 end:
10198   if (gamma) {
10199     *gamma = _gamma;
10200   }
10201   if (seqh) {
10202     *seqh = _seqh;
10203   } else if (_seqh) {
10204     gst_buffer_unref (_seqh);
10205   }
10206 }
10207
10208 static gchar *
10209 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10210 {
10211   GNode *dinf;
10212   GstByteReader dref;
10213   gchar *uri = NULL;
10214
10215   /*
10216    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10217    * atom that might contain a 'data' atom with the rtsp uri.
10218    * This case was reported in bug #597497, some info about
10219    * the hndl atom can be found in TN1195
10220    */
10221   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10222   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10223
10224   if (dinf) {
10225     guint32 dref_num_entries = 0;
10226     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10227         gst_byte_reader_skip (&dref, 4) &&
10228         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10229       gint i;
10230
10231       /* search dref entries for hndl atom */
10232       for (i = 0; i < dref_num_entries; i++) {
10233         guint32 size = 0, type;
10234         guint8 string_len = 0;
10235         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10236             qt_atom_parser_get_fourcc (&dref, &type)) {
10237           if (type == FOURCC_hndl) {
10238             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10239
10240             /* skip data reference handle bytes and the
10241              * following pascal string and some extra 4
10242              * bytes I have no idea what are */
10243             if (!gst_byte_reader_skip (&dref, 4) ||
10244                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10245                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10246               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10247               break;
10248             }
10249
10250             /* iterate over the atoms to find the data atom */
10251             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10252               guint32 atom_size;
10253               guint32 atom_type;
10254
10255               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10256                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10257                 if (atom_type == FOURCC_data) {
10258                   const guint8 *uri_aux = NULL;
10259
10260                   /* found the data atom that might contain the rtsp uri */
10261                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10262                       "hndl atom, interpreting it as an URI");
10263                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10264                           &uri_aux)) {
10265                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10266                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10267                     else
10268                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10269                           "didn't contain a rtsp address");
10270                   } else {
10271                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10272                         "atom contents");
10273                   }
10274                   break;
10275                 }
10276                 /* skipping to the next entry */
10277                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10278                   break;
10279               } else {
10280                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10281                     "atom header");
10282                 break;
10283               }
10284             }
10285             break;
10286           }
10287           /* skip to the next entry */
10288           if (!gst_byte_reader_skip (&dref, size - 8))
10289             break;
10290         } else {
10291           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10292         }
10293       }
10294       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10295     }
10296   }
10297   return uri;
10298 }
10299
10300 #define AMR_NB_ALL_MODES        0x81ff
10301 #define AMR_WB_ALL_MODES        0x83ff
10302 static guint
10303 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10304 {
10305   /* The 'damr' atom is of the form:
10306    *
10307    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10308    *    32 b       8 b          16 b           8 b                 8 b
10309    *
10310    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10311    * represents the highest mode used in the stream (and thus the maximum
10312    * bitrate), with a couple of special cases as seen below.
10313    */
10314
10315   /* Map of frame type ID -> bitrate */
10316   static const guint nb_bitrates[] = {
10317     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10318   };
10319   static const guint wb_bitrates[] = {
10320     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10321   };
10322   GstMapInfo map;
10323   gsize max_mode;
10324   guint16 mode_set;
10325
10326   gst_buffer_map (buf, &map, GST_MAP_READ);
10327
10328   if (map.size != 0x11) {
10329     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10330     goto bad_data;
10331   }
10332
10333   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10334     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10335         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10336     goto bad_data;
10337   }
10338
10339   mode_set = QT_UINT16 (map.data + 13);
10340
10341   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10342     max_mode = 7 + (wb ? 1 : 0);
10343   else
10344     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10345     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10346
10347   if (max_mode == -1) {
10348     GST_DEBUG ("No mode indication was found (mode set) = %x",
10349         (guint) mode_set);
10350     goto bad_data;
10351   }
10352
10353   gst_buffer_unmap (buf, &map);
10354   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10355
10356 bad_data:
10357   gst_buffer_unmap (buf, &map);
10358   return 0;
10359 }
10360
10361 static gboolean
10362 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10363     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10364 {
10365   /*
10366    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10367    * [0 1 2]
10368    * [3 4 5]
10369    * [6 7 8]
10370    */
10371
10372   if (gst_byte_reader_get_remaining (reader) < 36)
10373     return FALSE;
10374
10375   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10376   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10377   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10378   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10379   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10380   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10381   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10382   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10383   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10384
10385   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10386   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10387       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10388       matrix[2] & 0xFF);
10389   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10390       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10391       matrix[5] & 0xFF);
10392   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10393       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10394       matrix[8] & 0xFF);
10395
10396   return TRUE;
10397 }
10398
10399 static void
10400 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10401     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10402 {
10403
10404 /* [a b c]
10405  * [d e f]
10406  * [g h i]
10407  *
10408  * This macro will only compare value abdegh, it expects cfi to have already
10409  * been checked
10410  */
10411 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10412                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10413
10414   /* only handle the cases where the last column has standard values */
10415   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10416     const gchar *rotation_tag = NULL;
10417
10418     /* no rotation needed */
10419     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10420       /* NOP */
10421     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10422       rotation_tag = "rotate-90";
10423     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10424       rotation_tag = "rotate-180";
10425     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10426       rotation_tag = "rotate-270";
10427     } else {
10428       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10429     }
10430
10431     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10432         GST_STR_NULL (rotation_tag));
10433     if (rotation_tag != NULL) {
10434       if (*taglist == NULL)
10435         *taglist = gst_tag_list_new_empty ();
10436       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10437           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10438     }
10439   } else {
10440     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10441   }
10442 }
10443
10444 static gboolean
10445 qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
10446     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10447 {
10448   GNode *adrm;
10449   guint32 adrm_size;
10450   GstBuffer *adrm_buf = NULL;
10451   QtDemuxAavdEncryptionInfo *info;
10452
10453   adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
10454   if (G_UNLIKELY (!adrm)) {
10455     GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
10456     return FALSE;
10457   }
10458   adrm_size = QT_UINT32 (adrm->data);
10459   adrm_buf = gst_buffer_new_memdup (adrm->data, adrm_size);
10460
10461   stream->protection_scheme_type = FOURCC_aavd;
10462
10463   if (!stream->protection_scheme_info)
10464     stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
10465
10466   info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
10467
10468   if (info->default_properties)
10469     gst_structure_free (info->default_properties);
10470   info->default_properties = gst_structure_new ("application/x-aavd",
10471       "encrypted", G_TYPE_BOOLEAN, TRUE,
10472       "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
10473   gst_buffer_unref (adrm_buf);
10474
10475   *original_fmt = FOURCC_mp4a;
10476   return TRUE;
10477 }
10478
10479 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10480  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10481  * Common Encryption (cenc), the function will also parse the tenc box (defined
10482  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10483  * (typically an enc[v|a|t|s] sample entry); the function will set
10484  * @original_fmt to the fourcc of the original unencrypted stream format.
10485  * Returns TRUE if successful; FALSE otherwise. */
10486 static gboolean
10487 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10488     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10489 {
10490   GNode *sinf;
10491   GNode *frma;
10492   GNode *schm;
10493   GNode *schi;
10494   QtDemuxCencSampleSetInfo *info;
10495   GNode *tenc;
10496   const guint8 *tenc_data;
10497
10498   g_return_val_if_fail (qtdemux != NULL, FALSE);
10499   g_return_val_if_fail (stream != NULL, FALSE);
10500   g_return_val_if_fail (container != NULL, FALSE);
10501   g_return_val_if_fail (original_fmt != NULL, FALSE);
10502
10503   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10504   if (G_UNLIKELY (!sinf)) {
10505     if (stream->protection_scheme_type == FOURCC_cenc
10506         || stream->protection_scheme_type == FOURCC_cbcs) {
10507       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10508           "mandatory for Common Encryption");
10509       return FALSE;
10510     }
10511     return TRUE;
10512   }
10513
10514   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10515   if (G_UNLIKELY (!frma)) {
10516     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10517     return FALSE;
10518   }
10519
10520   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10521   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10522       GST_FOURCC_ARGS (*original_fmt));
10523
10524   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10525   if (!schm) {
10526     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10527     return FALSE;
10528   }
10529   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10530   stream->protection_scheme_version =
10531       QT_UINT32 ((const guint8 *) schm->data + 16);
10532
10533   GST_DEBUG_OBJECT (qtdemux,
10534       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10535       "protection_scheme_version: %#010x",
10536       GST_FOURCC_ARGS (stream->protection_scheme_type),
10537       stream->protection_scheme_version);
10538
10539   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10540   if (!schi) {
10541     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10542     return FALSE;
10543   }
10544   if (stream->protection_scheme_type != FOURCC_cenc &&
10545       stream->protection_scheme_type != FOURCC_piff &&
10546       stream->protection_scheme_type != FOURCC_cbcs) {
10547     GST_ERROR_OBJECT (qtdemux,
10548         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10549         GST_FOURCC_ARGS (stream->protection_scheme_type));
10550     return FALSE;
10551   }
10552
10553   if (G_UNLIKELY (!stream->protection_scheme_info))
10554     stream->protection_scheme_info =
10555         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10556
10557   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10558
10559   if (stream->protection_scheme_type == FOURCC_cenc
10560       || stream->protection_scheme_type == FOURCC_cbcs) {
10561     guint8 is_encrypted;
10562     guint8 iv_size;
10563     guint8 constant_iv_size = 0;
10564     const guint8 *default_kid;
10565     guint8 crypt_byte_block = 0;
10566     guint8 skip_byte_block = 0;
10567     const guint8 *constant_iv = NULL;
10568
10569     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10570     if (!tenc) {
10571       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10572           "which is mandatory for Common Encryption");
10573       return FALSE;
10574     }
10575     tenc_data = (const guint8 *) tenc->data + 12;
10576     is_encrypted = QT_UINT8 (tenc_data + 2);
10577     iv_size = QT_UINT8 (tenc_data + 3);
10578     default_kid = (tenc_data + 4);
10579     if (stream->protection_scheme_type == FOURCC_cbcs) {
10580       guint8 possible_pattern_info;
10581       if (iv_size == 0) {
10582         constant_iv_size = QT_UINT8 (tenc_data + 20);
10583         if (constant_iv_size != 8 && constant_iv_size != 16) {
10584           GST_ERROR_OBJECT (qtdemux,
10585               "constant IV size should be 8 or 16, not %hhu", constant_iv_size);
10586           return FALSE;
10587         }
10588         constant_iv = (tenc_data + 21);
10589       }
10590       possible_pattern_info = QT_UINT8 (tenc_data + 1);
10591       crypt_byte_block = (possible_pattern_info >> 4) & 0x0f;
10592       skip_byte_block = possible_pattern_info & 0x0f;
10593     }
10594     qtdemux_update_default_sample_cenc_settings (qtdemux, info,
10595         is_encrypted, stream->protection_scheme_type, iv_size, default_kid,
10596         crypt_byte_block, skip_byte_block, constant_iv_size, constant_iv);
10597   } else if (stream->protection_scheme_type == FOURCC_piff) {
10598     GstByteReader br;
10599     static const guint8 piff_track_encryption_uuid[] = {
10600       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10601       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10602     };
10603
10604     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10605     if (!tenc) {
10606       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10607           "which is mandatory for Common Encryption");
10608       return FALSE;
10609     }
10610
10611     tenc_data = (const guint8 *) tenc->data + 8;
10612     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10613       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10614       GST_ERROR_OBJECT (qtdemux,
10615           "Unsupported track encryption box with uuid: %s", box_uuid);
10616       g_free (box_uuid);
10617       return FALSE;
10618     }
10619     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10620     gst_byte_reader_init (&br, tenc_data, 20);
10621     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10622       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10623       return FALSE;
10624     }
10625     stream->protection_scheme_type = FOURCC_cenc;
10626   }
10627
10628   return TRUE;
10629 }
10630
10631 static gint
10632 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10633     QtDemuxStream ** stream2)
10634 {
10635   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10636 }
10637
10638 static gboolean
10639 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
10640     GNode * stbl)
10641 {
10642   GNode *svmi;
10643
10644   /*parse svmi header if existing */
10645   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10646   if (svmi) {
10647     guint len = QT_UINT32 ((guint8 *) svmi->data);
10648     guint32 version = QT_UINT32 ((guint8 *) svmi->data + 8);
10649     if (!version) {
10650       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10651       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10652       guint8 frame_type, frame_layout;
10653       guint32 stereo_mono_change_count;
10654
10655       if (len < 18)
10656         return FALSE;
10657
10658       /* MPEG-A stereo video */
10659       if (qtdemux->major_brand == FOURCC_ss02)
10660         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10661
10662       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10663       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10664       stereo_mono_change_count = QT_UINT32 ((guint8 *) svmi->data + 14);
10665
10666       switch (frame_type) {
10667         case 0:
10668           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10669           break;
10670         case 1:
10671           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10672           break;
10673         case 2:
10674           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10675           break;
10676         case 3:
10677           /* mode 3 is primary/secondary view sequence, ie
10678            * left/right views in separate tracks. See section 7.2
10679            * of ISO/IEC 23000-11:2009 */
10680           /* In the future this might be supported using related
10681            * streams, like an enhancement track - if files like this
10682            * ever exist */
10683           GST_FIXME_OBJECT (qtdemux,
10684               "Implement stereo video in separate streams");
10685       }
10686
10687       if ((frame_layout & 0x1) == 0)
10688         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10689
10690       GST_LOG_OBJECT (qtdemux,
10691           "StereoVideo: composition type: %u, is_left_first: %u",
10692           frame_type, frame_layout);
10693
10694       if (stereo_mono_change_count > 1) {
10695         GST_FIXME_OBJECT (qtdemux,
10696             "Mixed-mono flags are not yet supported in qtdemux.");
10697       }
10698
10699       stream->multiview_mode = mode;
10700       stream->multiview_flags = flags;
10701     }
10702   }
10703
10704   return TRUE;
10705 }
10706
10707 /* parse the traks.
10708  * With each track we associate a new QtDemuxStream that contains all the info
10709  * about the trak.
10710  * traks that do not decode to something (like strm traks) will not have a pad.
10711  */
10712 static gboolean
10713 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10714 {
10715   GstByteReader tkhd;
10716   int offset;
10717   GNode *mdia;
10718   GNode *mdhd;
10719   GNode *hdlr;
10720   GNode *minf;
10721   GNode *stbl;
10722   GNode *stsd;
10723   GNode *mp4a;
10724   GNode *mp4v;
10725   GNode *esds;
10726   GNode *tref;
10727   GNode *udta;
10728
10729   QtDemuxStream *stream = NULL;
10730   const guint8 *stsd_data;
10731   const guint8 *stsd_entry_data;
10732   guint remaining_stsd_len;
10733   guint stsd_entry_count;
10734   guint stsd_index;
10735   guint16 lang_code;            /* quicktime lang code or packed iso code */
10736   guint32 version;
10737   guint32 tkhd_flags = 0;
10738   guint8 tkhd_version = 0;
10739   guint32 w = 0, h = 0;
10740   guint value_size, stsd_len, len;
10741   guint32 track_id;
10742   guint32 dummy;
10743
10744   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10745
10746   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10747       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10748       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10749     goto corrupt_file;
10750
10751   /* pick between 64 or 32 bits */
10752   value_size = tkhd_version == 1 ? 8 : 4;
10753   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10754       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10755     goto corrupt_file;
10756
10757   /* Check if current moov has duplicated track_id */
10758   if (qtdemux_find_stream (qtdemux, track_id))
10759     goto existing_stream;
10760
10761   stream = _create_stream (qtdemux, track_id);
10762   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10763
10764   /* need defaults for fragments */
10765   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10766
10767   if ((tkhd_flags & 1) == 0)
10768     stream->disabled = TRUE;
10769
10770   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10771       tkhd_version, tkhd_flags, stream->track_id);
10772
10773   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10774     goto corrupt_file;
10775
10776   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10777     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10778     if (qtdemux->major_brand != FOURCC_mjp2 ||
10779         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10780       goto corrupt_file;
10781   }
10782
10783   len = QT_UINT32 ((guint8 *) mdhd->data);
10784   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10785   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10786   if (version == 0x01000000) {
10787     if (len < 42)
10788       goto corrupt_file;
10789     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10790     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10791     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10792   } else {
10793     if (len < 30)
10794       goto corrupt_file;
10795     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10796     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10797     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10798   }
10799
10800   if (lang_code < 0x400) {
10801     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10802   } else if (lang_code == 0x7fff) {
10803     stream->lang_id[0] = 0;     /* unspecified */
10804   } else {
10805     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10806     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10807     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10808     stream->lang_id[3] = 0;
10809   }
10810
10811   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10812       stream->timescale);
10813   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10814       stream->duration);
10815   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10816       lang_code, stream->lang_id);
10817
10818   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10819     goto corrupt_file;
10820
10821   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10822     /* chapters track reference */
10823     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10824     if (chap) {
10825       gsize length = GST_READ_UINT32_BE (chap->data);
10826       if (qtdemux->chapters_track_id)
10827         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10828
10829       if (length >= 12) {
10830         qtdemux->chapters_track_id =
10831             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10832       }
10833     }
10834   }
10835
10836   /* fragmented files may have bogus duration in moov */
10837   if (!qtdemux->fragmented &&
10838       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10839     guint64 tdur1, tdur2;
10840
10841     /* don't overflow */
10842     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10843     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10844
10845     /* HACK:
10846      * some of those trailers, nowadays, have prologue images that are
10847      * themselves video tracks as well. I haven't really found a way to
10848      * identify those yet, except for just looking at their duration. */
10849     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10850       GST_WARNING_OBJECT (qtdemux,
10851           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10852           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10853           "found, assuming preview image or something; skipping track",
10854           stream->duration, stream->timescale, qtdemux->duration,
10855           qtdemux->timescale);
10856       gst_qtdemux_stream_unref (stream);
10857       return TRUE;
10858     }
10859   }
10860
10861   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10862     goto corrupt_file;
10863
10864   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10865       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10866
10867   len = QT_UINT32 ((guint8 *) hdlr->data);
10868   if (len >= 20)
10869     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10870   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10871       GST_FOURCC_ARGS (stream->subtype));
10872
10873   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10874     goto corrupt_file;
10875
10876   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10877     goto corrupt_file;
10878
10879   /* Parse out svmi (and later st3d/sv3d) atoms */
10880   if (!qtdemux_parse_stereo_svmi_atom (qtdemux, stream, stbl))
10881     goto corrupt_file;
10882
10883   /* parse rest of tkhd */
10884   if (stream->subtype == FOURCC_vide) {
10885     guint32 matrix[9];
10886
10887     /* version 1 uses some 64-bit ints */
10888     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10889       goto corrupt_file;
10890
10891     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10892       goto corrupt_file;
10893
10894     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10895         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10896       goto corrupt_file;
10897
10898     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10899         &stream->stream_tags);
10900   }
10901
10902   /* parse stsd */
10903   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10904     goto corrupt_file;
10905   stsd_data = (const guint8 *) stsd->data;
10906
10907   /* stsd should at least have one entry */
10908   stsd_len = QT_UINT32 (stsd_data);
10909   if (stsd_len < 24) {
10910     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10911     if (stream->subtype == FOURCC_vivo) {
10912       gst_qtdemux_stream_unref (stream);
10913       return TRUE;
10914     } else {
10915       goto corrupt_file;
10916     }
10917   }
10918
10919   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10920   /* each stsd entry must contain at least 8 bytes */
10921   if (stream->stsd_entries_length == 0
10922       || stream->stsd_entries_length > stsd_len / 8) {
10923     stream->stsd_entries_length = 0;
10924     goto corrupt_file;
10925   }
10926   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10927   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10928   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10929
10930   stsd_entry_data = stsd_data + 16;
10931   remaining_stsd_len = stsd_len - 16;
10932   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10933     guint32 fourcc;
10934     gchar *codec = NULL;
10935     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10936
10937     /* and that entry should fit within stsd */
10938     len = QT_UINT32 (stsd_entry_data);
10939     if (len > remaining_stsd_len)
10940       goto corrupt_file;
10941
10942     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10943     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10944         GST_FOURCC_ARGS (entry->fourcc));
10945     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10946
10947     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10948       goto error_encrypted;
10949
10950     if (fourcc == FOURCC_aavd) {
10951       if (stream->subtype != FOURCC_soun) {
10952         GST_ERROR_OBJECT (qtdemux,
10953             "Unexpeced stsd type 'aavd' outside 'soun' track");
10954       } else {
10955         /* encrypted audio with sound sample description v0 */
10956         GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10957         stream->protected = TRUE;
10958         if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
10959           GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10960       }
10961     }
10962
10963     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10964       /* FIXME this looks wrong, there might be multiple children
10965        * with the same type */
10966       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10967       stream->protected = TRUE;
10968       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10969         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10970     }
10971
10972     if (stream->subtype == FOURCC_vide) {
10973       GNode *colr;
10974       GNode *fiel;
10975       GNode *pasp;
10976       gboolean gray;
10977       gint depth, palette_size, palette_count;
10978       guint32 *palette_data = NULL;
10979
10980       entry->sampled = TRUE;
10981
10982       stream->display_width = w >> 16;
10983       stream->display_height = h >> 16;
10984
10985       offset = 16;
10986       if (len < 86)             /* TODO verify */
10987         goto corrupt_file;
10988
10989       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10990       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10991       entry->fps_n = 0;         /* this is filled in later */
10992       entry->fps_d = 0;         /* this is filled in later */
10993       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10994       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10995
10996       /* if color_table_id is 0, ctab atom must follow; however some files
10997        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10998        * if color table is not present we'll correct the value */
10999       if (entry->color_table_id == 0 &&
11000           (len < 90
11001               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
11002         entry->color_table_id = -1;
11003       }
11004
11005       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
11006           entry->width, entry->height, entry->bits_per_sample,
11007           entry->color_table_id);
11008
11009       depth = entry->bits_per_sample;
11010
11011       /* more than 32 bits means grayscale */
11012       gray = (depth > 32);
11013       /* low 32 bits specify the depth  */
11014       depth &= 0x1F;
11015
11016       /* different number of palette entries is determined by depth. */
11017       palette_count = 0;
11018       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
11019         palette_count = (1 << depth);
11020       palette_size = palette_count * 4;
11021
11022       if (entry->color_table_id) {
11023         switch (palette_count) {
11024           case 0:
11025             break;
11026           case 2:
11027             palette_data = g_memdup2 (ff_qt_default_palette_2, palette_size);
11028             break;
11029           case 4:
11030             palette_data = g_memdup2 (ff_qt_default_palette_4, palette_size);
11031             break;
11032           case 16:
11033             if (gray)
11034               palette_data =
11035                   g_memdup2 (ff_qt_grayscale_palette_16, palette_size);
11036             else
11037               palette_data = g_memdup2 (ff_qt_default_palette_16, palette_size);
11038             break;
11039           case 256:
11040             if (gray)
11041               palette_data =
11042                   g_memdup2 (ff_qt_grayscale_palette_256, palette_size);
11043             else
11044               palette_data =
11045                   g_memdup2 (ff_qt_default_palette_256, palette_size);
11046             break;
11047           default:
11048             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11049                 (_("The video in this file might not play correctly.")),
11050                 ("unsupported palette depth %d", depth));
11051             break;
11052         }
11053       } else {
11054         gint i, j, start, end;
11055
11056         if (len < 94)
11057           goto corrupt_file;
11058
11059         /* read table */
11060         start = QT_UINT32 (stsd_entry_data + offset + 70);
11061         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
11062         end = QT_UINT16 (stsd_entry_data + offset + 76);
11063
11064         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
11065             start, end, palette_count);
11066
11067         if (end > 255)
11068           end = 255;
11069         if (start > end)
11070           start = end;
11071
11072         if (len < 94 + (end - start) * 8)
11073           goto corrupt_file;
11074
11075         /* palette is always the same size */
11076         palette_data = g_malloc0 (256 * 4);
11077         palette_size = 256 * 4;
11078
11079         for (j = 0, i = start; i <= end; j++, i++) {
11080           guint32 a, r, g, b;
11081
11082           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
11083           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
11084           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
11085           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
11086
11087           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
11088               (g & 0xff00) | (b >> 8);
11089         }
11090       }
11091
11092       if (entry->caps)
11093         gst_caps_unref (entry->caps);
11094
11095       entry->caps =
11096           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11097           &codec);
11098       if (G_UNLIKELY (!entry->caps)) {
11099         g_free (palette_data);
11100         goto unknown_stream;
11101       }
11102
11103       if (codec) {
11104         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11105             GST_TAG_VIDEO_CODEC, codec, NULL);
11106         g_free (codec);
11107         codec = NULL;
11108       }
11109
11110       if (palette_data) {
11111         GstStructure *s;
11112
11113         if (entry->rgb8_palette)
11114           gst_memory_unref (entry->rgb8_palette);
11115         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
11116             palette_data, palette_size, 0, palette_size, palette_data, g_free);
11117
11118         s = gst_caps_get_structure (entry->caps, 0);
11119
11120         /* non-raw video has a palette_data property. raw video has the palette as
11121          * an extra plane that we append to the output buffers before we push
11122          * them*/
11123         if (!gst_structure_has_name (s, "video/x-raw")) {
11124           GstBuffer *palette;
11125
11126           palette = gst_buffer_new ();
11127           gst_buffer_append_memory (palette, entry->rgb8_palette);
11128           entry->rgb8_palette = NULL;
11129
11130           gst_caps_set_simple (entry->caps, "palette_data",
11131               GST_TYPE_BUFFER, palette, NULL);
11132           gst_buffer_unref (palette);
11133         }
11134       } else if (palette_count != 0) {
11135         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
11136             (NULL), ("Unsupported palette depth %d", depth));
11137       }
11138
11139       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
11140           QT_UINT16 (stsd_entry_data + offset + 32));
11141
11142       esds = NULL;
11143       pasp = NULL;
11144       colr = NULL;
11145       fiel = NULL;
11146       /* pick 'the' stsd child */
11147       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11148       // We should skip parsing the stsd for non-protected streams if
11149       // the entry doesn't match the fourcc, since they don't change
11150       // format. However, for protected streams we can have partial
11151       // encryption, where parts of the stream are encrypted and parts
11152       // not. For both parts of such streams, we should ensure the
11153       // esds overrides are parsed for both from the stsd.
11154       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
11155         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
11156           mp4v = NULL;
11157         else if (!stream->protected)
11158           mp4v = NULL;
11159       }
11160
11161       if (mp4v) {
11162         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
11163         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
11164         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
11165         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
11166       }
11167
11168       if (pasp) {
11169         const guint8 *pasp_data = (const guint8 *) pasp->data;
11170         gint len = QT_UINT32 (pasp_data);
11171
11172         if (len == 16) {
11173           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
11174           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
11175         } else {
11176           CUR_STREAM (stream)->par_w = 0;
11177           CUR_STREAM (stream)->par_h = 0;
11178         }
11179       } else {
11180         CUR_STREAM (stream)->par_w = 0;
11181         CUR_STREAM (stream)->par_h = 0;
11182       }
11183
11184       if (fiel) {
11185         const guint8 *fiel_data = (const guint8 *) fiel->data;
11186         gint len = QT_UINT32 (fiel_data);
11187
11188         if (len == 10) {
11189           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
11190           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
11191         }
11192       }
11193
11194       if (colr) {
11195         const guint8 *colr_data = (const guint8 *) colr->data;
11196         gint len = QT_UINT32 (colr_data);
11197
11198         if (len == 19 || len == 18) {
11199           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
11200
11201           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
11202             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
11203             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
11204             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
11205             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
11206
11207             CUR_STREAM (stream)->colorimetry.primaries =
11208                 gst_video_color_primaries_from_iso (primaries);
11209             CUR_STREAM (stream)->colorimetry.transfer =
11210                 gst_video_transfer_function_from_iso (transfer_function);
11211             CUR_STREAM (stream)->colorimetry.matrix =
11212                 gst_video_color_matrix_from_iso (matrix);
11213             CUR_STREAM (stream)->colorimetry.range =
11214                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
11215                 GST_VIDEO_COLOR_RANGE_16_235;
11216           } else {
11217             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
11218           }
11219         } else {
11220           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
11221         }
11222       }
11223
11224       if (esds) {
11225         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11226             stream->stream_tags);
11227       } else {
11228         switch (fourcc) {
11229           case FOURCC_H264:
11230           case FOURCC_avc1:
11231           case FOURCC_avc3:
11232           {
11233             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11234             const guint8 *avc_data = stsd_entry_data + 0x56;
11235
11236             /* find avcC */
11237             while (len >= 0x8) {
11238               gint size;
11239
11240               if (QT_UINT32 (avc_data) <= len)
11241                 size = QT_UINT32 (avc_data) - 0x8;
11242               else
11243                 size = len - 0x8;
11244
11245               if (size < 1)
11246                 /* No real data, so break out */
11247                 break;
11248
11249               switch (QT_FOURCC (avc_data + 0x4)) {
11250                 case FOURCC_avcC:
11251                 {
11252                   /* parse, if found */
11253                   GstBuffer *buf;
11254
11255                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11256
11257                   /* First 4 bytes are the length of the atom, the next 4 bytes
11258                    * are the fourcc, the next 1 byte is the version, and the
11259                    * subsequent bytes are profile_tier_level structure like data. */
11260                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11261                       avc_data + 8 + 1, size - 1);
11262                   buf = gst_buffer_new_and_alloc (size);
11263                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11264                   gst_caps_set_simple (entry->caps,
11265                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11266                   gst_buffer_unref (buf);
11267
11268                   break;
11269                 }
11270                 case FOURCC_strf:
11271                 {
11272                   GstBuffer *buf;
11273
11274                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11275
11276                   /* First 4 bytes are the length of the atom, the next 4 bytes
11277                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11278                    * next 1 byte is the version, and the
11279                    * subsequent bytes are sequence parameter set like data. */
11280
11281                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11282                   if (size > 1) {
11283                     gst_codec_utils_h264_caps_set_level_and_profile
11284                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11285
11286                     buf = gst_buffer_new_and_alloc (size);
11287                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11288                     gst_caps_set_simple (entry->caps,
11289                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11290                     gst_buffer_unref (buf);
11291                   }
11292                   break;
11293                 }
11294                 case FOURCC_btrt:
11295                 {
11296                   guint avg_bitrate, max_bitrate;
11297
11298                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11299                   if (size < 12)
11300                     break;
11301
11302                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11303                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11304
11305                   if (!max_bitrate && !avg_bitrate)
11306                     break;
11307
11308                   /* Some muxers seem to swap the average and maximum bitrates
11309                    * (I'm looking at you, YouTube), so we swap for sanity. */
11310                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11311                     guint temp = avg_bitrate;
11312
11313                     avg_bitrate = max_bitrate;
11314                     max_bitrate = temp;
11315                   }
11316
11317                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11318                     gst_tag_list_add (stream->stream_tags,
11319                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11320                         max_bitrate, NULL);
11321                   }
11322                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11323                     gst_tag_list_add (stream->stream_tags,
11324                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11325                         NULL);
11326                   }
11327
11328                   break;
11329                 }
11330
11331                 default:
11332                   break;
11333               }
11334
11335               len -= size + 8;
11336               avc_data += size + 8;
11337             }
11338
11339             break;
11340           }
11341           case FOURCC_H265:
11342           case FOURCC_hvc1:
11343           case FOURCC_hev1:
11344           case FOURCC_dvh1:
11345           case FOURCC_dvhe:
11346           {
11347             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11348             const guint8 *hevc_data = stsd_entry_data + 0x56;
11349
11350             /* find hevc */
11351             while (len >= 0x8) {
11352               gint size;
11353
11354               if (QT_UINT32 (hevc_data) <= len)
11355                 size = QT_UINT32 (hevc_data) - 0x8;
11356               else
11357                 size = len - 0x8;
11358
11359               if (size < 1)
11360                 /* No real data, so break out */
11361                 break;
11362
11363               switch (QT_FOURCC (hevc_data + 0x4)) {
11364                 case FOURCC_hvcC:
11365                 {
11366                   /* parse, if found */
11367                   GstBuffer *buf;
11368
11369                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11370
11371                   /* First 4 bytes are the length of the atom, the next 4 bytes
11372                    * are the fourcc, the next 1 byte is the version, and the
11373                    * subsequent bytes are sequence parameter set like data. */
11374                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11375                       (entry->caps, hevc_data + 8 + 1, size - 1);
11376
11377                   buf = gst_buffer_new_and_alloc (size);
11378                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11379                   gst_caps_set_simple (entry->caps,
11380                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11381                   gst_buffer_unref (buf);
11382                   break;
11383                 }
11384                 default:
11385                   break;
11386               }
11387               len -= size + 8;
11388               hevc_data += size + 8;
11389             }
11390             break;
11391           }
11392           case FOURCC_mp4v:
11393           case FOURCC_MP4V:
11394           case FOURCC_fmp4:
11395           case FOURCC_FMP4:
11396           case FOURCC_xvid:
11397           case FOURCC_XVID:
11398           {
11399             GNode *glbl;
11400
11401             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11402                 GST_FOURCC_ARGS (fourcc));
11403
11404             /* codec data might be in glbl extension atom */
11405             glbl = mp4v ?
11406                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11407             if (glbl) {
11408               guint8 *data;
11409               GstBuffer *buf;
11410               gint len;
11411
11412               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11413               data = glbl->data;
11414               len = QT_UINT32 (data);
11415               if (len > 0x8) {
11416                 len -= 0x8;
11417                 buf = gst_buffer_new_and_alloc (len);
11418                 gst_buffer_fill (buf, 0, data + 8, len);
11419                 gst_caps_set_simple (entry->caps,
11420                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11421                 gst_buffer_unref (buf);
11422               }
11423             }
11424             break;
11425           }
11426           case FOURCC_mjp2:
11427           {
11428             /* see annex I of the jpeg2000 spec */
11429             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11430             const guint8 *data;
11431             const gchar *colorspace = NULL;
11432             gint ncomp = 0;
11433             guint32 ncomp_map = 0;
11434             gint32 *comp_map = NULL;
11435             guint32 nchan_def = 0;
11436             gint32 *chan_def = NULL;
11437
11438             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11439             /* some required atoms */
11440             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11441             if (!mjp2)
11442               break;
11443             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11444             if (!jp2h)
11445               break;
11446
11447             /* number of components; redundant with info in codestream, but useful
11448                to a muxer */
11449             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11450             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11451               break;
11452             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11453
11454             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11455             if (!colr)
11456               break;
11457             GST_DEBUG_OBJECT (qtdemux, "found colr");
11458             /* extract colour space info */
11459             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11460               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11461                 case 16:
11462                   colorspace = "sRGB";
11463                   break;
11464                 case 17:
11465                   colorspace = "GRAY";
11466                   break;
11467                 case 18:
11468                   colorspace = "sYUV";
11469                   break;
11470                 default:
11471                   colorspace = NULL;
11472                   break;
11473               }
11474             }
11475             if (!colorspace)
11476               /* colr is required, and only values 16, 17, and 18 are specified,
11477                  so error if we have no colorspace */
11478               break;
11479
11480             /* extract component mapping */
11481             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11482             if (cmap) {
11483               guint32 cmap_len = 0;
11484               int i;
11485               cmap_len = QT_UINT32 (cmap->data);
11486               if (cmap_len >= 8) {
11487                 /* normal box, subtract off header */
11488                 cmap_len -= 8;
11489                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11490                 if (cmap_len % 4 == 0) {
11491                   ncomp_map = (cmap_len / 4);
11492                   comp_map = g_new0 (gint32, ncomp_map);
11493                   for (i = 0; i < ncomp_map; i++) {
11494                     guint16 cmp;
11495                     guint8 mtyp, pcol;
11496                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11497                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11498                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11499                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11500                   }
11501                 }
11502               }
11503             }
11504             /* extract channel definitions */
11505             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11506             if (cdef) {
11507               guint32 cdef_len = 0;
11508               int i;
11509               cdef_len = QT_UINT32 (cdef->data);
11510               if (cdef_len >= 10) {
11511                 /* normal box, subtract off header and len */
11512                 cdef_len -= 10;
11513                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11514                 if (cdef_len % 6 == 0) {
11515                   nchan_def = (cdef_len / 6);
11516                   chan_def = g_new0 (gint32, nchan_def);
11517                   for (i = 0; i < nchan_def; i++)
11518                     chan_def[i] = -1;
11519                   for (i = 0; i < nchan_def; i++) {
11520                     guint16 cn, typ, asoc;
11521                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11522                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11523                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11524                     if (cn < nchan_def) {
11525                       switch (typ) {
11526                         case 0:
11527                           chan_def[cn] = asoc;
11528                           break;
11529                         case 1:
11530                           chan_def[cn] = 0;     /* alpha */
11531                           break;
11532                         default:
11533                           chan_def[cn] = -typ;
11534                       }
11535                     }
11536                   }
11537                 }
11538               }
11539             }
11540
11541             gst_caps_set_simple (entry->caps,
11542                 "num-components", G_TYPE_INT, ncomp, NULL);
11543             gst_caps_set_simple (entry->caps,
11544                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11545
11546             if (comp_map) {
11547               GValue arr = { 0, };
11548               GValue elt = { 0, };
11549               int i;
11550               g_value_init (&arr, GST_TYPE_ARRAY);
11551               g_value_init (&elt, G_TYPE_INT);
11552               for (i = 0; i < ncomp_map; i++) {
11553                 g_value_set_int (&elt, comp_map[i]);
11554                 gst_value_array_append_value (&arr, &elt);
11555               }
11556               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11557                   "component-map", &arr);
11558               g_value_unset (&elt);
11559               g_value_unset (&arr);
11560               g_free (comp_map);
11561             }
11562
11563             if (chan_def) {
11564               GValue arr = { 0, };
11565               GValue elt = { 0, };
11566               int i;
11567               g_value_init (&arr, GST_TYPE_ARRAY);
11568               g_value_init (&elt, G_TYPE_INT);
11569               for (i = 0; i < nchan_def; i++) {
11570                 g_value_set_int (&elt, chan_def[i]);
11571                 gst_value_array_append_value (&arr, &elt);
11572               }
11573               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11574                   "channel-definitions", &arr);
11575               g_value_unset (&elt);
11576               g_value_unset (&arr);
11577               g_free (chan_def);
11578             }
11579
11580             /* some optional atoms */
11581             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11582             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11583
11584             /* indicate possible fields in caps */
11585             if (field) {
11586               data = (guint8 *) field->data + 8;
11587               if (*data != 1)
11588                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11589                     (gint) * data, NULL);
11590             }
11591             /* add codec_data if provided */
11592             if (prefix) {
11593               GstBuffer *buf;
11594               gint len;
11595
11596               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11597               data = prefix->data;
11598               len = QT_UINT32 (data);
11599               if (len > 0x8) {
11600                 len -= 0x8;
11601                 buf = gst_buffer_new_and_alloc (len);
11602                 gst_buffer_fill (buf, 0, data + 8, len);
11603                 gst_caps_set_simple (entry->caps,
11604                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11605                 gst_buffer_unref (buf);
11606               }
11607             }
11608             break;
11609           }
11610           case FOURCC_SVQ3:
11611           case FOURCC_VP31:
11612           {
11613             GstBuffer *buf;
11614             GstBuffer *seqh = NULL;
11615             const guint8 *gamma_data = NULL;
11616             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11617
11618             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11619                 &seqh);
11620             if (gamma_data) {
11621               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11622                   QT_FP32 (gamma_data), NULL);
11623             }
11624             if (seqh) {
11625               /* sorry for the bad name, but we don't know what this is, other
11626                * than its own fourcc */
11627               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11628                   NULL);
11629               gst_buffer_unref (seqh);
11630             }
11631
11632             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11633             buf = gst_buffer_new_and_alloc (len);
11634             gst_buffer_fill (buf, 0, stsd_data, len);
11635             gst_caps_set_simple (entry->caps,
11636                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11637             gst_buffer_unref (buf);
11638             break;
11639           }
11640           case FOURCC_jpeg:
11641           {
11642             /* https://developer.apple.com/standards/qtff-2001.pdf,
11643              * page 92, "Video Sample Description", under table 3.1 */
11644             GstByteReader br;
11645
11646             const gint compressor_offset =
11647                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11648             const gint min_size = compressor_offset + 32 + 2 + 2;
11649             GNode *jpeg;
11650             guint32 len;
11651             guint16 color_table_id = 0;
11652             gboolean ok;
11653
11654             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11655
11656             /* recover information on interlaced/progressive */
11657             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11658             if (!jpeg)
11659               break;
11660
11661             len = QT_UINT32 (jpeg->data);
11662             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11663                 min_size);
11664             if (len >= min_size) {
11665               gst_byte_reader_init (&br, jpeg->data, len);
11666
11667               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11668               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11669               if (color_table_id != 0) {
11670                 /* the spec says there can be concatenated chunks in the data, and we want
11671                  * to find one called field. Walk through them. */
11672                 gint offset = min_size;
11673                 while (offset + 8 < len) {
11674                   guint32 size = 0, tag;
11675                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11676                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11677                   if (!ok || size < 8) {
11678                     GST_WARNING_OBJECT (qtdemux,
11679                         "Failed to walk optional chunk list");
11680                     break;
11681                   }
11682                   GST_DEBUG_OBJECT (qtdemux,
11683                       "Found optional %4.4s chunk, size %u",
11684                       (const char *) &tag, size);
11685                   if (tag == FOURCC_fiel) {
11686                     guint8 n_fields = 0, ordering = 0;
11687                     gst_byte_reader_get_uint8 (&br, &n_fields);
11688                     gst_byte_reader_get_uint8 (&br, &ordering);
11689                     if (n_fields == 1 || n_fields == 2) {
11690                       GST_DEBUG_OBJECT (qtdemux,
11691                           "Found fiel tag with %u fields, ordering %u",
11692                           n_fields, ordering);
11693                       if (n_fields == 2)
11694                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11695                             "interlace-mode", G_TYPE_STRING, "interleaved",
11696                             NULL);
11697                     } else {
11698                       GST_WARNING_OBJECT (qtdemux,
11699                           "Found fiel tag with invalid fields (%u)", n_fields);
11700                     }
11701                   }
11702                   offset += size;
11703                 }
11704               } else {
11705                 GST_DEBUG_OBJECT (qtdemux,
11706                     "Color table ID is 0, not trying to get interlacedness");
11707               }
11708             } else {
11709               GST_WARNING_OBJECT (qtdemux,
11710                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11711             }
11712
11713             break;
11714           }
11715           case FOURCC_rle_:
11716           case FOURCC_WRLE:
11717           {
11718             gst_caps_set_simple (entry->caps,
11719                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11720                 NULL);
11721             break;
11722           }
11723           case FOURCC_XiTh:
11724           {
11725             GNode *xith, *xdxt;
11726
11727             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11728             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11729             if (!xith)
11730               break;
11731
11732             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11733             if (!xdxt)
11734               break;
11735
11736             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11737             /* collect the headers and store them in a stream list so that we can
11738              * send them out first */
11739             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11740             break;
11741           }
11742           case FOURCC_ovc1:
11743           {
11744             GNode *ovc1;
11745             guint8 *ovc1_data;
11746             guint ovc1_len;
11747             GstBuffer *buf;
11748
11749             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11750             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11751             if (!ovc1)
11752               break;
11753             ovc1_data = ovc1->data;
11754             ovc1_len = QT_UINT32 (ovc1_data);
11755             if (ovc1_len <= 198) {
11756               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11757               break;
11758             }
11759             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11760             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11761             gst_caps_set_simple (entry->caps,
11762                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11763             gst_buffer_unref (buf);
11764             break;
11765           }
11766           case FOURCC_vc_1:
11767           {
11768             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11769             const guint8 *vc1_data = stsd_entry_data + 0x56;
11770
11771             /* find dvc1 */
11772             while (len >= 8) {
11773               gint size;
11774
11775               if (QT_UINT32 (vc1_data) <= len)
11776                 size = QT_UINT32 (vc1_data) - 8;
11777               else
11778                 size = len - 8;
11779
11780               if (size < 1)
11781                 /* No real data, so break out */
11782                 break;
11783
11784               switch (QT_FOURCC (vc1_data + 0x4)) {
11785                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11786                 {
11787                   GstBuffer *buf;
11788
11789                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11790                   buf = gst_buffer_new_and_alloc (size);
11791                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11792                   gst_caps_set_simple (entry->caps,
11793                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11794                   gst_buffer_unref (buf);
11795                   break;
11796                 }
11797                 default:
11798                   break;
11799               }
11800               len -= size + 8;
11801               vc1_data += size + 8;
11802             }
11803             break;
11804           }
11805           case FOURCC_av01:
11806           {
11807             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11808             const guint8 *av1_data = stsd_entry_data + 0x56;
11809
11810             /* find av1C */
11811             while (len >= 0x8) {
11812               gint size;
11813
11814               if (QT_UINT32 (av1_data) <= len)
11815                 size = QT_UINT32 (av1_data) - 0x8;
11816               else
11817                 size = len - 0x8;
11818
11819               if (size < 1)
11820                 /* No real data, so break out */
11821                 break;
11822
11823               switch (QT_FOURCC (av1_data + 0x4)) {
11824                 case FOURCC_av1C:
11825                 {
11826                   /* parse, if found */
11827                   GstBuffer *buf;
11828                   guint8 pres_delay_field;
11829
11830                   GST_DEBUG_OBJECT (qtdemux,
11831                       "found av1C codec_data in stsd of size %d", size);
11832
11833                   /* not enough data, just ignore and hope for the best */
11834                   if (size < 5)
11835                     break;
11836
11837                   /* Content is:
11838                    * 4 bytes: atom length
11839                    * 4 bytes: fourcc
11840                    * 1 byte: version
11841                    * 3 bytes: flags
11842                    * 3 bits: reserved
11843                    * 1 bits:  initial_presentation_delay_present
11844                    * 4 bits: initial_presentation_delay (if present else reserved
11845                    * rest: OBUs.
11846                    */
11847
11848                   if (av1_data[9] != 0) {
11849                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11850                     break;
11851                   }
11852
11853                   /* We skip initial_presentation_delay* for now */
11854                   pres_delay_field = *(av1_data + 12);
11855                   if (pres_delay_field & (1 << 5)) {
11856                     gst_caps_set_simple (entry->caps,
11857                         "presentation-delay", G_TYPE_INT,
11858                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11859                   }
11860                   if (size > 5) {
11861                     buf = gst_buffer_new_and_alloc (size - 5);
11862                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11863                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11864                     gst_caps_set_simple (entry->caps,
11865                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11866                     gst_buffer_unref (buf);
11867                   }
11868                   break;
11869                 }
11870                 default:
11871                   break;
11872               }
11873
11874               len -= size + 8;
11875               av1_data += size + 8;
11876             }
11877
11878             break;
11879           }
11880
11881             /* TODO: Need to parse vpcC for VP8 codec too.
11882              * Note that VPCodecConfigurationBox (vpcC) is defined for
11883              * vp08, vp09, and vp10 fourcc. */
11884           case FOURCC_vp09:
11885           {
11886             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11887             const guint8 *vpcc_data = stsd_entry_data + 0x56;
11888
11889             /* find vpcC */
11890             while (len >= 0x8) {
11891               gint size;
11892
11893               if (QT_UINT32 (vpcc_data) <= len)
11894                 size = QT_UINT32 (vpcc_data) - 0x8;
11895               else
11896                 size = len - 0x8;
11897
11898               if (size < 1)
11899                 /* No real data, so break out */
11900                 break;
11901
11902               switch (QT_FOURCC (vpcc_data + 0x4)) {
11903                 case FOURCC_vpcC:
11904                 {
11905                   const gchar *profile_str = NULL;
11906                   const gchar *chroma_format_str = NULL;
11907                   guint8 profile;
11908                   guint8 bitdepth;
11909                   guint8 chroma_format;
11910                   GstVideoColorimetry cinfo;
11911
11912                   /* parse, if found */
11913                   GST_DEBUG_OBJECT (qtdemux,
11914                       "found vp codec_data in stsd of size %d", size);
11915
11916                   /* the meaning of "size" is length of the atom body, excluding
11917                    * atom length and fourcc fields */
11918                   if (size < 12)
11919                     break;
11920
11921                   /* Content is:
11922                    * 4 bytes: atom length
11923                    * 4 bytes: fourcc
11924                    * 1 byte: version
11925                    * 3 bytes: flags
11926                    * 1 byte: profile
11927                    * 1 byte: level
11928                    * 4 bits: bitDepth
11929                    * 3 bits: chromaSubsampling
11930                    * 1 bit: videoFullRangeFlag
11931                    * 1 byte: colourPrimaries
11932                    * 1 byte: transferCharacteristics
11933                    * 1 byte: matrixCoefficients
11934                    * 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
11935                    * rest: codecIntializationData (not used for vp8 and vp9)
11936                    */
11937
11938                   if (vpcc_data[8] != 1) {
11939                     GST_WARNING_OBJECT (qtdemux,
11940                         "unknown vpcC version %d", vpcc_data[8]);
11941                     break;
11942                   }
11943
11944                   profile = vpcc_data[12];
11945                   switch (profile) {
11946                     case 0:
11947                       profile_str = "0";
11948                       break;
11949                     case 1:
11950                       profile_str = "1";
11951                       break;
11952                     case 2:
11953                       profile_str = "2";
11954                       break;
11955                     case 3:
11956                       profile_str = "3";
11957                       break;
11958                     default:
11959                       break;
11960                   }
11961
11962                   if (profile_str) {
11963                     gst_caps_set_simple (entry->caps,
11964                         "profile", G_TYPE_STRING, profile_str, NULL);
11965                   }
11966
11967                   /* skip level, the VP9 spec v0.6 defines only one level atm,
11968                    * but webm spec define various ones. Add level to caps
11969                    * if we really need it then */
11970
11971                   bitdepth = (vpcc_data[14] & 0xf0) >> 4;
11972                   if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
11973                     gst_caps_set_simple (entry->caps,
11974                         "bit-depth-luma", G_TYPE_UINT, bitdepth,
11975                         "bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
11976                   }
11977
11978                   chroma_format = (vpcc_data[14] & 0xe) >> 1;
11979                   switch (chroma_format) {
11980                     case 0:
11981                     case 1:
11982                       chroma_format_str = "4:2:0";
11983                       break;
11984                     case 2:
11985                       chroma_format_str = "4:2:2";
11986                       break;
11987                     case 3:
11988                       chroma_format_str = "4:4:4";
11989                       break;
11990                     default:
11991                       break;
11992                   }
11993
11994                   if (chroma_format_str) {
11995                     gst_caps_set_simple (entry->caps,
11996                         "chroma-format", G_TYPE_STRING, chroma_format_str,
11997                         NULL);
11998                   }
11999
12000                   if ((vpcc_data[14] & 0x1) != 0)
12001                     cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
12002                   else
12003                     cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
12004                   cinfo.primaries =
12005                       gst_video_color_primaries_from_iso (vpcc_data[15]);
12006                   cinfo.transfer =
12007                       gst_video_transfer_function_from_iso (vpcc_data[16]);
12008                   cinfo.matrix =
12009                       gst_video_color_matrix_from_iso (vpcc_data[17]);
12010
12011                   if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
12012                       cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
12013                       cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
12014                     /* set this only if all values are known, otherwise this
12015                      * might overwrite valid ones parsed from other color box */
12016                     CUR_STREAM (stream)->colorimetry = cinfo;
12017                   }
12018                   break;
12019                 }
12020                 default:
12021                   break;
12022               }
12023
12024               len -= size + 8;
12025               vpcc_data += size + 8;
12026             }
12027
12028             break;
12029           }
12030           default:
12031             break;
12032         }
12033       }
12034
12035       GST_INFO_OBJECT (qtdemux,
12036           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12037           GST_FOURCC_ARGS (fourcc), entry->caps);
12038
12039     } else if (stream->subtype == FOURCC_soun) {
12040       GNode *wave;
12041       int version, samplesize;
12042       guint16 compression_id;
12043       gboolean amrwb = FALSE;
12044
12045       offset = 16;
12046       /* sample description entry (16) + sound sample description v0 (20) */
12047       if (len < 36)
12048         goto corrupt_file;
12049
12050       version = QT_UINT32 (stsd_entry_data + offset);
12051       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
12052       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
12053       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
12054       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
12055
12056       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
12057       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
12058           QT_UINT32 (stsd_entry_data + offset + 4));
12059       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
12060       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
12061       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
12062       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
12063           QT_UINT16 (stsd_entry_data + offset + 14));
12064       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
12065
12066       if (compression_id == 0xfffe)
12067         entry->sampled = TRUE;
12068
12069       /* first assume uncompressed audio */
12070       entry->bytes_per_sample = samplesize / 8;
12071       entry->samples_per_frame = entry->n_channels;
12072       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12073       entry->samples_per_packet = entry->samples_per_frame;
12074       entry->bytes_per_packet = entry->bytes_per_sample;
12075
12076       offset = 36;
12077
12078       if (version == 0x00010000) {
12079         /* sample description entry (16) + sound sample description v1 (20+16) */
12080         if (len < 52)
12081           goto corrupt_file;
12082
12083         /* take information from here over the normal sample description */
12084         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
12085         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
12086         entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
12087         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
12088
12089         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 1");
12090         GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
12091             entry->samples_per_packet);
12092         GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
12093             entry->bytes_per_packet);
12094         GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
12095             entry->bytes_per_frame);
12096         GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
12097             entry->bytes_per_sample);
12098
12099         if (!entry->sampled && entry->bytes_per_packet) {
12100           entry->samples_per_frame = (entry->bytes_per_frame /
12101               entry->bytes_per_packet) * entry->samples_per_packet;
12102           GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
12103               entry->samples_per_frame);
12104         }
12105       } else if (version == 0x00020000) {
12106         /* sample description entry (16) + sound sample description v2 (56) */
12107         if (len < 72)
12108           goto corrupt_file;
12109
12110         /* take information from here over the normal sample description */
12111         entry->rate = GST_READ_DOUBLE_BE (stsd_entry_data + offset + 4);
12112         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
12113         entry->samples_per_frame = entry->n_channels;
12114         entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 20) / 8;
12115         entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 28);
12116         entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset + 32);
12117         entry->bytes_per_frame = entry->bytes_per_sample * entry->n_channels;
12118
12119         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
12120         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
12121         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
12122         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
12123             entry->bytes_per_sample * 8);
12124         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
12125             QT_UINT32 (stsd_entry_data + offset + 24));
12126         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
12127             entry->bytes_per_packet);
12128         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
12129             entry->samples_per_packet);
12130       } else if (version != 0x00000) {
12131         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
12132             version);
12133       }
12134
12135       switch (fourcc) {
12136           /* Yes, these have to be hard-coded */
12137         case FOURCC_MAC6:
12138         {
12139           entry->samples_per_packet = 6;
12140           entry->bytes_per_packet = 1;
12141           entry->bytes_per_frame = 1 * entry->n_channels;
12142           entry->bytes_per_sample = 1;
12143           entry->samples_per_frame = 6 * entry->n_channels;
12144           break;
12145         }
12146         case FOURCC_MAC3:
12147         {
12148           entry->samples_per_packet = 3;
12149           entry->bytes_per_packet = 1;
12150           entry->bytes_per_frame = 1 * entry->n_channels;
12151           entry->bytes_per_sample = 1;
12152           entry->samples_per_frame = 3 * entry->n_channels;
12153           break;
12154         }
12155         case FOURCC_ima4:
12156         {
12157           entry->samples_per_packet = 64;
12158           entry->bytes_per_packet = 34;
12159           entry->bytes_per_frame = 34 * entry->n_channels;
12160           entry->bytes_per_sample = 2;
12161           entry->samples_per_frame = 64 * entry->n_channels;
12162           break;
12163         }
12164         case FOURCC_ulaw:
12165         case FOURCC_alaw:
12166         {
12167           entry->samples_per_packet = 1;
12168           entry->bytes_per_packet = 1;
12169           entry->bytes_per_frame = 1 * entry->n_channels;
12170           entry->bytes_per_sample = 1;
12171           entry->samples_per_frame = 1 * entry->n_channels;
12172           break;
12173         }
12174         case FOURCC_agsm:
12175         {
12176           entry->samples_per_packet = 160;
12177           entry->bytes_per_packet = 33;
12178           entry->bytes_per_frame = 33 * entry->n_channels;
12179           entry->bytes_per_sample = 2;
12180           entry->samples_per_frame = 160 * entry->n_channels;
12181           break;
12182         }
12183           /* fix up any invalid header information from above */
12184         case FOURCC_twos:
12185         case FOURCC_sowt:
12186         case FOURCC_raw_:
12187         case FOURCC_lpcm:
12188           /* Sometimes these are set to 0 in the sound sample descriptions so
12189            * let's try to infer useful values from the other information we
12190            * have available */
12191           if (entry->bytes_per_sample == 0)
12192             entry->bytes_per_sample =
12193                 entry->bytes_per_frame / entry->n_channels;
12194           if (entry->bytes_per_sample == 0)
12195             entry->bytes_per_sample = samplesize / 8;
12196
12197           if (entry->bytes_per_frame == 0)
12198             entry->bytes_per_frame =
12199                 entry->bytes_per_sample * entry->n_channels;
12200
12201           if (entry->bytes_per_packet == 0)
12202             entry->bytes_per_packet = entry->bytes_per_sample;
12203
12204           if (entry->samples_per_frame == 0)
12205             entry->samples_per_frame = entry->n_channels;
12206
12207           if (entry->samples_per_packet == 0)
12208             entry->samples_per_packet = entry->samples_per_frame;
12209
12210           break;
12211         case FOURCC_in24:
12212         case FOURCC_in32:
12213         case FOURCC_fl32:
12214         case FOURCC_fl64:
12215         case FOURCC_s16l:{
12216           switch (fourcc) {
12217             case FOURCC_in24:
12218               entry->bytes_per_sample = 3;
12219               break;
12220             case FOURCC_in32:
12221             case FOURCC_fl32:
12222               entry->bytes_per_sample = 4;
12223               break;
12224             case FOURCC_fl64:
12225               entry->bytes_per_sample = 8;
12226               break;
12227             case FOURCC_s16l:
12228               entry->bytes_per_sample = 2;
12229               break;
12230             default:
12231               g_assert_not_reached ();
12232               break;
12233           }
12234           entry->samples_per_frame = entry->n_channels;
12235           entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
12236           entry->samples_per_packet = entry->samples_per_frame;
12237           entry->bytes_per_packet = entry->bytes_per_sample;
12238           break;
12239         }
12240         default:
12241           break;
12242       }
12243
12244       if (entry->caps)
12245         gst_caps_unref (entry->caps);
12246
12247       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
12248           stsd_entry_data + 32, len - 16, &codec);
12249
12250       switch (fourcc) {
12251         case FOURCC_in24:
12252         case FOURCC_in32:
12253         case FOURCC_fl32:
12254         case FOURCC_fl64:
12255         {
12256           GNode *enda;
12257           GNode *fmt;
12258
12259           fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
12260
12261           enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
12262           if (!enda) {
12263             wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
12264             if (wave)
12265               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
12266           }
12267           if (enda) {
12268             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
12269             const gchar *format_str;
12270
12271             switch (fourcc) {
12272               case FOURCC_in24:
12273                 format_str = (enda_value) ? "S24LE" : "S24BE";
12274                 break;
12275               case FOURCC_in32:
12276                 format_str = (enda_value) ? "S32LE" : "S32BE";
12277                 break;
12278               case FOURCC_fl32:
12279                 format_str = (enda_value) ? "F32LE" : "F32BE";
12280                 break;
12281               case FOURCC_fl64:
12282                 format_str = (enda_value) ? "F64LE" : "F64BE";
12283                 break;
12284               default:
12285                 g_assert_not_reached ();
12286                 break;
12287             }
12288             gst_caps_set_simple (entry->caps,
12289                 "format", G_TYPE_STRING, format_str, NULL);
12290           }
12291           break;
12292         }
12293         case FOURCC_owma:
12294         {
12295           const guint8 *owma_data;
12296           const gchar *codec_name = NULL;
12297           guint owma_len;
12298           GstBuffer *buf;
12299           gint version = 1;
12300           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12301           /* FIXME this should also be gst_riff_strf_auds,
12302            * but the latter one is actually missing bits-per-sample :( */
12303           typedef struct
12304           {
12305             gint16 wFormatTag;
12306             gint16 nChannels;
12307             gint32 nSamplesPerSec;
12308             gint32 nAvgBytesPerSec;
12309             gint16 nBlockAlign;
12310             gint16 wBitsPerSample;
12311             gint16 cbSize;
12312           } WAVEFORMATEX;
12313           WAVEFORMATEX *wfex;
12314
12315           GST_DEBUG_OBJECT (qtdemux, "parse owma");
12316           owma_data = stsd_entry_data;
12317           owma_len = QT_UINT32 (owma_data);
12318           if (owma_len <= 54) {
12319             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
12320             break;
12321           }
12322           wfex = (WAVEFORMATEX *) (owma_data + 36);
12323           buf = gst_buffer_new_and_alloc (owma_len - 54);
12324           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
12325           if (wfex->wFormatTag == 0x0161) {
12326             codec_name = "Windows Media Audio";
12327             version = 2;
12328           } else if (wfex->wFormatTag == 0x0162) {
12329             codec_name = "Windows Media Audio 9 Pro";
12330             version = 3;
12331           } else if (wfex->wFormatTag == 0x0163) {
12332             codec_name = "Windows Media Audio 9 Lossless";
12333             /* is that correct? gstffmpegcodecmap.c is missing it, but
12334              * fluendo codec seems to support it */
12335             version = 4;
12336           }
12337
12338           gst_caps_set_simple (entry->caps,
12339               "codec_data", GST_TYPE_BUFFER, buf,
12340               "wmaversion", G_TYPE_INT, version,
12341               "block_align", G_TYPE_INT,
12342               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
12343               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
12344               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
12345               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
12346           gst_buffer_unref (buf);
12347
12348           if (codec_name) {
12349             g_free (codec);
12350             codec = g_strdup (codec_name);
12351           }
12352           break;
12353         }
12354         case FOURCC_wma_:
12355         {
12356           gint len = QT_UINT32 (stsd_entry_data) - offset;
12357           const guint8 *wfex_data = stsd_entry_data + offset;
12358           const gchar *codec_name = NULL;
12359           gint version = 1;
12360           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
12361           /* FIXME this should also be gst_riff_strf_auds,
12362            * but the latter one is actually missing bits-per-sample :( */
12363           typedef struct
12364           {
12365             gint16 wFormatTag;
12366             gint16 nChannels;
12367             gint32 nSamplesPerSec;
12368             gint32 nAvgBytesPerSec;
12369             gint16 nBlockAlign;
12370             gint16 wBitsPerSample;
12371             gint16 cbSize;
12372           } WAVEFORMATEX;
12373           WAVEFORMATEX wfex;
12374
12375           /* FIXME: unify with similar wavformatex parsing code above */
12376           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
12377
12378           /* find wfex */
12379           while (len >= 8) {
12380             gint size;
12381
12382             if (QT_UINT32 (wfex_data) <= len)
12383               size = QT_UINT32 (wfex_data) - 8;
12384             else
12385               size = len - 8;
12386
12387             if (size < 1)
12388               /* No real data, so break out */
12389               break;
12390
12391             switch (QT_FOURCC (wfex_data + 4)) {
12392               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
12393               {
12394                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
12395
12396                 if (size < 8 + 18)
12397                   break;
12398
12399                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
12400                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
12401                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
12402                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
12403                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
12404                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
12405                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
12406
12407                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
12408                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
12409                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
12410                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
12411                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
12412                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
12413
12414                 if (wfex.wFormatTag == 0x0161) {
12415                   codec_name = "Windows Media Audio";
12416                   version = 2;
12417                 } else if (wfex.wFormatTag == 0x0162) {
12418                   codec_name = "Windows Media Audio 9 Pro";
12419                   version = 3;
12420                 } else if (wfex.wFormatTag == 0x0163) {
12421                   codec_name = "Windows Media Audio 9 Lossless";
12422                   /* is that correct? gstffmpegcodecmap.c is missing it, but
12423                    * fluendo codec seems to support it */
12424                   version = 4;
12425                 }
12426
12427                 gst_caps_set_simple (entry->caps,
12428                     "wmaversion", G_TYPE_INT, version,
12429                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
12430                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
12431                     "width", G_TYPE_INT, wfex.wBitsPerSample,
12432                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
12433
12434                 if (size > wfex.cbSize) {
12435                   GstBuffer *buf;
12436
12437                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
12438                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
12439                       size - wfex.cbSize);
12440                   gst_caps_set_simple (entry->caps,
12441                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
12442                   gst_buffer_unref (buf);
12443                 } else {
12444                   GST_WARNING_OBJECT (qtdemux, "no codec data");
12445                 }
12446
12447                 if (codec_name) {
12448                   g_free (codec);
12449                   codec = g_strdup (codec_name);
12450                 }
12451                 break;
12452               }
12453               default:
12454                 break;
12455             }
12456             len -= size + 8;
12457             wfex_data += size + 8;
12458           }
12459           break;
12460         }
12461         case FOURCC_opus:
12462         {
12463           const guint8 *dops_data;
12464           guint8 *channel_mapping = NULL;
12465           guint32 rate;
12466           guint8 channels;
12467           guint8 channel_mapping_family;
12468           guint8 stream_count;
12469           guint8 coupled_count;
12470           guint8 i;
12471
12472           version = GST_READ_UINT16_BE (stsd_entry_data + 16);
12473           if (version == 1)
12474             dops_data = stsd_entry_data + 51;
12475           else
12476             dops_data = stsd_entry_data + 35;
12477
12478           channels = GST_READ_UINT8 (dops_data + 10);
12479           rate = GST_READ_UINT32_LE (dops_data + 13);
12480           channel_mapping_family = GST_READ_UINT8 (dops_data + 19);
12481           stream_count = GST_READ_UINT8 (dops_data + 20);
12482           coupled_count = GST_READ_UINT8 (dops_data + 21);
12483
12484           if (channels > 0) {
12485             channel_mapping = g_malloc (channels * sizeof (guint8));
12486             for (i = 0; i < channels; i++)
12487               channel_mapping[i] = GST_READ_UINT8 (dops_data + i + 22);
12488           }
12489
12490           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12491               channel_mapping_family, stream_count, coupled_count,
12492               channel_mapping);
12493           break;
12494         }
12495         default:
12496           break;
12497       }
12498
12499       if (codec) {
12500         GstStructure *s;
12501         gint bitrate = 0;
12502
12503         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12504             GST_TAG_AUDIO_CODEC, codec, NULL);
12505         g_free (codec);
12506         codec = NULL;
12507
12508         /* some bitrate info may have ended up in caps */
12509         s = gst_caps_get_structure (entry->caps, 0);
12510         gst_structure_get_int (s, "bitrate", &bitrate);
12511         if (bitrate > 0)
12512           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12513               GST_TAG_BITRATE, bitrate, NULL);
12514       }
12515
12516       esds = NULL;
12517       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12518       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12519         if (stream->protected) {
12520           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
12521             esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12522           }
12523           if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12524             mp4a = NULL;
12525           }
12526         } else {
12527           mp4a = NULL;
12528         }
12529       }
12530
12531       wave = NULL;
12532       if (mp4a) {
12533         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12534         if (wave)
12535           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12536         if (!esds)
12537           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12538       }
12539
12540
12541       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12542          16 bits is a byte-swapped wave-style codec identifier,
12543          and we can find a WAVE header internally to a 'wave' atom here.
12544          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12545          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12546          is big-endian).
12547        */
12548       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12549         if (len < offset + 20) {
12550           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12551         } else {
12552           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12553           const guint8 *data = stsd_entry_data + offset + 16;
12554           GNode *wavenode;
12555           GNode *waveheadernode;
12556
12557           wavenode = g_node_new ((guint8 *) data);
12558           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12559             const guint8 *waveheader;
12560             guint32 headerlen;
12561
12562             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12563             if (waveheadernode) {
12564               waveheader = (const guint8 *) waveheadernode->data;
12565               headerlen = QT_UINT32 (waveheader);
12566
12567               if (headerlen > 8) {
12568                 gst_riff_strf_auds *header = NULL;
12569                 GstBuffer *headerbuf;
12570                 GstBuffer *extra;
12571
12572                 waveheader += 8;
12573                 headerlen -= 8;
12574
12575                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12576                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12577
12578                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12579                         headerbuf, &header, &extra)) {
12580                   gst_caps_unref (entry->caps);
12581                   /* FIXME: Need to do something with the channel reorder map */
12582                   entry->caps =
12583                       gst_riff_create_audio_caps (header->format, NULL, header,
12584                       extra, NULL, NULL, NULL);
12585
12586                   if (extra)
12587                     gst_buffer_unref (extra);
12588                   g_free (header);
12589                 }
12590               }
12591             } else
12592               GST_DEBUG ("Didn't find waveheadernode for this codec");
12593           }
12594           g_node_destroy (wavenode);
12595         }
12596       } else if (esds) {
12597         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12598             stream->stream_tags);
12599       } else {
12600         switch (fourcc) {
12601 #if 0
12602             /* FIXME: what is in the chunk? */
12603           case FOURCC_QDMC:
12604           {
12605             gint len = QT_UINT32 (stsd_data);
12606
12607             /* seems to be always = 116 = 0x74 */
12608             break;
12609           }
12610 #endif
12611           case FOURCC_QDM2:
12612           {
12613             gint len = QT_UINT32 (stsd_entry_data);
12614
12615             if (len > 0x3C) {
12616               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12617
12618               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12619               gst_caps_set_simple (entry->caps,
12620                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12621               gst_buffer_unref (buf);
12622             }
12623             gst_caps_set_simple (entry->caps,
12624                 "samplesize", G_TYPE_INT, samplesize, NULL);
12625             break;
12626           }
12627           case FOURCC_alac:
12628           {
12629             GNode *alac, *wave = NULL;
12630
12631             /* apparently, m4a has this atom appended directly in the stsd entry,
12632              * while mov has it in a wave atom */
12633             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12634             if (alac) {
12635               /* alac now refers to stsd entry atom */
12636               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12637               if (wave)
12638                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12639               else
12640                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12641             }
12642             if (alac) {
12643               const guint8 *alac_data = alac->data;
12644               gint len = QT_UINT32 (alac->data);
12645               GstBuffer *buf;
12646
12647               if (len < 36) {
12648                 GST_DEBUG_OBJECT (qtdemux,
12649                     "discarding alac atom with unexpected len %d", len);
12650               } else {
12651                 /* codec-data contains alac atom size and prefix,
12652                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12653                 buf = gst_buffer_new_and_alloc (len);
12654                 gst_buffer_fill (buf, 0, alac->data, len);
12655                 gst_caps_set_simple (entry->caps,
12656                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12657                 gst_buffer_unref (buf);
12658
12659                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12660                 entry->n_channels = QT_UINT8 (alac_data + 21);
12661                 entry->rate = QT_UINT32 (alac_data + 32);
12662                 samplesize = QT_UINT8 (alac_data + 16 + 1);
12663               }
12664             }
12665             gst_caps_set_simple (entry->caps,
12666                 "samplesize", G_TYPE_INT, samplesize, NULL);
12667             break;
12668           }
12669           case FOURCC_fLaC:
12670           {
12671             /* The codingname of the sample entry is 'fLaC' */
12672             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12673
12674             if (flac) {
12675               /* The 'dfLa' box is added to the sample entry to convey
12676                  initializing information for the decoder. */
12677               const GNode *dfla =
12678                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12679
12680               if (dfla) {
12681                 const guint32 len = QT_UINT32 (dfla->data);
12682
12683                 /* Must contain at least dfLa box header (12),
12684                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12685                 if (len < 50) {
12686                   GST_DEBUG_OBJECT (qtdemux,
12687                       "discarding dfla atom with unexpected len %d", len);
12688                 } else {
12689                   /* skip dfLa header to get the METADATA_BLOCKs */
12690                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12691                   const guint32 metadata_blocks_len = len - 12;
12692
12693                   gchar *stream_marker = g_strdup ("fLaC");
12694                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12695                       strlen (stream_marker));
12696
12697                   guint32 index = 0;
12698                   guint32 remainder = 0;
12699                   guint32 block_size = 0;
12700                   gboolean is_last = FALSE;
12701
12702                   GValue array = G_VALUE_INIT;
12703                   GValue value = G_VALUE_INIT;
12704
12705                   g_value_init (&array, GST_TYPE_ARRAY);
12706                   g_value_init (&value, GST_TYPE_BUFFER);
12707
12708                   gst_value_set_buffer (&value, block);
12709                   gst_value_array_append_value (&array, &value);
12710                   g_value_reset (&value);
12711
12712                   gst_buffer_unref (block);
12713
12714                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12715                    * of data, and we haven't already finished parsing */
12716                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12717                     remainder = metadata_blocks_len - index;
12718
12719                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12720                     block_size = 4 +
12721                         (metadata_blocks[index + 1] << 16) +
12722                         (metadata_blocks[index + 2] << 8) +
12723                         metadata_blocks[index + 3];
12724
12725                     /* be careful not to read off end of box */
12726                     if (block_size > remainder) {
12727                       break;
12728                     }
12729
12730                     is_last = metadata_blocks[index] >> 7;
12731
12732                     block = gst_buffer_new_and_alloc (block_size);
12733
12734                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12735                         block_size);
12736
12737                     gst_value_set_buffer (&value, block);
12738                     gst_value_array_append_value (&array, &value);
12739                     g_value_reset (&value);
12740
12741                     gst_buffer_unref (block);
12742
12743                     index += block_size;
12744                   }
12745
12746                   /* only append the metadata if we successfully read all of it */
12747                   if (is_last) {
12748                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12749                             (stream)->caps, 0), "streamheader", &array);
12750                   } else {
12751                     GST_WARNING_OBJECT (qtdemux,
12752                         "discarding all METADATA_BLOCKs due to invalid "
12753                         "block_size %d at idx %d, rem %d", block_size, index,
12754                         remainder);
12755                   }
12756
12757                   g_value_unset (&value);
12758                   g_value_unset (&array);
12759
12760                   /* The sample rate obtained from the stsd may not be accurate
12761                    * since it cannot represent rates greater than 65535Hz, so
12762                    * override that value with the sample rate from the
12763                    * METADATA_BLOCK_STREAMINFO block */
12764                   CUR_STREAM (stream)->rate =
12765                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12766                 }
12767               }
12768             }
12769             break;
12770           }
12771           case FOURCC_sawb:
12772             /* Fallthrough! */
12773             amrwb = TRUE;
12774           case FOURCC_samr:
12775           {
12776             gint len = QT_UINT32 (stsd_entry_data);
12777
12778             if (len > 0x24) {
12779               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12780               guint bitrate;
12781
12782               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12783
12784               /* If we have enough data, let's try to get the 'damr' atom. See
12785                * the 3GPP container spec (26.244) for more details. */
12786               if ((len - 0x34) > 8 &&
12787                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12788                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12789                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12790               }
12791
12792               gst_caps_set_simple (entry->caps,
12793                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12794               gst_buffer_unref (buf);
12795             }
12796             break;
12797           }
12798           case FOURCC_mp4a:
12799           {
12800             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12801             gint len = QT_UINT32 (stsd_entry_data);
12802             guint16 sound_version = 0;
12803             /* FIXME: Can this be determined somehow? There doesn't seem to be
12804              * anything in mp4a atom that specifis compression */
12805             gint profile = 2;
12806             guint16 channels = entry->n_channels;
12807             guint32 time_scale = (guint32) entry->rate;
12808             gint sample_rate_index = -1;
12809
12810             if (len >= 34) {
12811               sound_version = QT_UINT16 (stsd_entry_data + 16);
12812
12813               if (sound_version == 1) {
12814                 channels = QT_UINT16 (stsd_entry_data + 24);
12815                 time_scale = QT_UINT32 (stsd_entry_data + 30);
12816               } else {
12817                 GST_FIXME_OBJECT (qtdemux, "Unhandled mp4a atom version %d",
12818                     sound_version);
12819               }
12820             } else {
12821               GST_DEBUG_OBJECT (qtdemux, "Too small stsd entry data len %d",
12822                   len);
12823             }
12824
12825             sample_rate_index =
12826                 gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12827             if (sample_rate_index >= 0 && channels > 0) {
12828               guint8 codec_data[2];
12829               GstBuffer *buf;
12830
12831               /* build AAC codec data */
12832               codec_data[0] = profile << 3;
12833               codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12834               codec_data[1] = (sample_rate_index & 0x01) << 7;
12835               codec_data[1] |= (channels & 0xF) << 3;
12836
12837               buf = gst_buffer_new_and_alloc (2);
12838               gst_buffer_fill (buf, 0, codec_data, 2);
12839               gst_caps_set_simple (entry->caps,
12840                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12841               gst_buffer_unref (buf);
12842             }
12843             break;
12844           }
12845           case FOURCC_lpcm:
12846           case FOURCC_in24:
12847           case FOURCC_in32:
12848           case FOURCC_fl32:
12849           case FOURCC_fl64:
12850           case FOURCC_s16l:
12851             /* Fully handled elsewhere */
12852             break;
12853           default:
12854             GST_INFO_OBJECT (qtdemux,
12855                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12856             break;
12857         }
12858       }
12859       GST_INFO_OBJECT (qtdemux,
12860           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12861           GST_FOURCC_ARGS (fourcc), entry->caps);
12862
12863     } else if (stream->subtype == FOURCC_strm) {
12864       if (fourcc == FOURCC_rtsp) {
12865         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12866       } else {
12867         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12868             GST_FOURCC_ARGS (fourcc));
12869         goto unknown_stream;
12870       }
12871       entry->sampled = TRUE;
12872     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12873         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12874         || stream->subtype == FOURCC_clcp || stream->subtype == FOURCC_wvtt) {
12875
12876       entry->sampled = TRUE;
12877       entry->sparse = TRUE;
12878
12879       entry->caps =
12880           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12881           &codec);
12882       if (codec) {
12883         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12884             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12885         g_free (codec);
12886         codec = NULL;
12887       }
12888
12889       /* hunt for sort-of codec data */
12890       switch (fourcc) {
12891         case FOURCC_mp4s:
12892         {
12893           GNode *mp4s = NULL;
12894           GNode *esds = NULL;
12895
12896           /* look for palette in a stsd->mp4s->esds sub-atom */
12897           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12898           if (mp4s)
12899             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12900           if (esds == NULL) {
12901             /* Invalid STSD */
12902             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12903             break;
12904           }
12905
12906           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12907               stream->stream_tags);
12908           break;
12909         }
12910         default:
12911           GST_INFO_OBJECT (qtdemux,
12912               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12913           break;
12914       }
12915       GST_INFO_OBJECT (qtdemux,
12916           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12917           GST_FOURCC_ARGS (fourcc), entry->caps);
12918     } else {
12919       /* everything in 1 sample */
12920       entry->sampled = TRUE;
12921
12922       entry->caps =
12923           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12924           &codec);
12925
12926       if (entry->caps == NULL)
12927         goto unknown_stream;
12928
12929       if (codec) {
12930         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12931             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12932         g_free (codec);
12933         codec = NULL;
12934       }
12935     }
12936
12937     /* promote to sampled format */
12938     if (entry->fourcc == FOURCC_samr) {
12939       /* force mono 8000 Hz for AMR */
12940       entry->sampled = TRUE;
12941       entry->n_channels = 1;
12942       entry->rate = 8000;
12943     } else if (entry->fourcc == FOURCC_sawb) {
12944       /* force mono 16000 Hz for AMR-WB */
12945       entry->sampled = TRUE;
12946       entry->n_channels = 1;
12947       entry->rate = 16000;
12948     } else if (entry->fourcc == FOURCC_mp4a) {
12949       entry->sampled = TRUE;
12950     }
12951
12952
12953     stsd_entry_data += len;
12954     remaining_stsd_len -= len;
12955
12956   }
12957
12958   /* collect sample information */
12959   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12960     goto samples_failed;
12961
12962   if (qtdemux->fragmented) {
12963     guint64 offset;
12964
12965     /* need all moov samples as basis; probably not many if any at all */
12966     /* prevent moof parsing taking of at this time */
12967     offset = qtdemux->moof_offset;
12968     qtdemux->moof_offset = 0;
12969     if (stream->n_samples &&
12970         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12971       qtdemux->moof_offset = offset;
12972       goto samples_failed;
12973     }
12974     qtdemux->moof_offset = offset;
12975     /* movie duration more reliable in this case (e.g. mehd) */
12976     if (qtdemux->segment.duration &&
12977         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12978       stream->duration =
12979           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12980   }
12981
12982   /* configure segments */
12983   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12984     goto segments_failed;
12985
12986   /* add some language tag, if useful */
12987   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12988       strcmp (stream->lang_id, "und")) {
12989     const gchar *lang_code;
12990
12991     /* convert ISO 639-2 code to ISO 639-1 */
12992     lang_code = gst_tag_get_language_code (stream->lang_id);
12993     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12994         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12995   }
12996
12997   /* Check for UDTA tags */
12998   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12999     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
13000   }
13001
13002   /* Insert and sort new stream in track-id order.
13003    * This will help in comparing old/new streams during stream update check */
13004   g_ptr_array_add (qtdemux->active_streams, stream);
13005   g_ptr_array_sort (qtdemux->active_streams,
13006       (GCompareFunc) qtdemux_track_id_compare_func);
13007   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
13008       QTDEMUX_N_STREAMS (qtdemux));
13009
13010   return TRUE;
13011
13012 /* ERRORS */
13013 corrupt_file:
13014   {
13015     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
13016         (_("This file is corrupt and cannot be played.")), (NULL));
13017     if (stream)
13018       gst_qtdemux_stream_unref (stream);
13019     return FALSE;
13020   }
13021 error_encrypted:
13022   {
13023     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
13024     gst_qtdemux_stream_unref (stream);
13025     return FALSE;
13026   }
13027 samples_failed:
13028 segments_failed:
13029   {
13030     /* we posted an error already */
13031     /* free stbl sub-atoms */
13032     gst_qtdemux_stbl_free (stream);
13033     gst_qtdemux_stream_unref (stream);
13034     return FALSE;
13035   }
13036 existing_stream:
13037   {
13038     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
13039         track_id);
13040     return TRUE;
13041   }
13042 unknown_stream:
13043   {
13044     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
13045         GST_FOURCC_ARGS (stream->subtype));
13046     gst_qtdemux_stream_unref (stream);
13047     return TRUE;
13048   }
13049 }
13050
13051 /* If we can estimate the overall bitrate, and don't have information about the
13052  * stream bitrate for exactly one stream, this guesses the stream bitrate as
13053  * the overall bitrate minus the sum of the bitrates of all other streams. This
13054  * should be useful for the common case where we have one audio and one video
13055  * stream and can estimate the bitrate of one, but not the other. */
13056 static void
13057 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
13058 {
13059   QtDemuxStream *stream = NULL;
13060   gint64 size, sys_bitrate, sum_bitrate = 0;
13061   GstClockTime duration;
13062   guint bitrate;
13063   gint i;
13064
13065   if (qtdemux->fragmented)
13066     return;
13067
13068   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
13069
13070   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
13071       || size <= 0) {
13072     GST_DEBUG_OBJECT (qtdemux,
13073         "Size in bytes of the stream not known - bailing");
13074     return;
13075   }
13076
13077   /* Subtract the header size */
13078   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
13079       size, qtdemux->header_size);
13080
13081   if (size < qtdemux->header_size)
13082     return;
13083
13084   size = size - qtdemux->header_size;
13085
13086   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
13087     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
13088     return;
13089   }
13090
13091   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13092     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
13093     switch (str->subtype) {
13094       case FOURCC_soun:
13095       case FOURCC_vide:
13096         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
13097             CUR_STREAM (str)->caps);
13098         /* retrieve bitrate, prefer avg then max */
13099         bitrate = 0;
13100         if (str->stream_tags) {
13101           if (gst_tag_list_get_uint (str->stream_tags,
13102                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
13103             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
13104           if (gst_tag_list_get_uint (str->stream_tags,
13105                   GST_TAG_NOMINAL_BITRATE, &bitrate))
13106             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
13107           if (gst_tag_list_get_uint (str->stream_tags,
13108                   GST_TAG_BITRATE, &bitrate))
13109             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
13110         }
13111         if (bitrate)
13112           sum_bitrate += bitrate;
13113         else {
13114           if (stream) {
13115             GST_DEBUG_OBJECT (qtdemux,
13116                 ">1 stream with unknown bitrate - bailing");
13117             return;
13118           } else
13119             stream = str;
13120         }
13121
13122       default:
13123         /* For other subtypes, we assume no significant impact on bitrate */
13124         break;
13125     }
13126   }
13127
13128   if (!stream) {
13129     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
13130     return;
13131   }
13132
13133   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
13134
13135   if (sys_bitrate < sum_bitrate) {
13136     /* This can happen, since sum_bitrate might be derived from maximum
13137      * bitrates and not average bitrates */
13138     GST_DEBUG_OBJECT (qtdemux,
13139         "System bitrate less than sum bitrate - bailing");
13140     return;
13141   }
13142
13143   bitrate = sys_bitrate - sum_bitrate;
13144   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
13145       ", Stream bitrate = %u", sys_bitrate, bitrate);
13146
13147   if (!stream->stream_tags)
13148     stream->stream_tags = gst_tag_list_new_empty ();
13149   else
13150     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
13151
13152   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
13153       GST_TAG_BITRATE, bitrate, NULL);
13154 }
13155
13156 static GstFlowReturn
13157 qtdemux_prepare_streams (GstQTDemux * qtdemux)
13158 {
13159   GstFlowReturn ret = GST_FLOW_OK;
13160   gint i;
13161
13162   GST_DEBUG_OBJECT (qtdemux, "prepare %u streams", QTDEMUX_N_STREAMS (qtdemux));
13163
13164   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13165     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13166     guint32 sample_num = 0;
13167
13168     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13169         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13170
13171     if (qtdemux->fragmented && qtdemux->pullbased) {
13172       /* need all moov samples first */
13173       GST_OBJECT_LOCK (qtdemux);
13174       while (stream->n_samples == 0)
13175         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
13176           break;
13177       GST_OBJECT_UNLOCK (qtdemux);
13178     } else {
13179       /* discard any stray moof */
13180       qtdemux->moof_offset = 0;
13181     }
13182
13183     /* prepare braking */
13184     if (ret != GST_FLOW_ERROR)
13185       ret = GST_FLOW_OK;
13186
13187     /* in pull mode, we should have parsed some sample info by now;
13188      * and quite some code will not handle no samples.
13189      * in push mode, we'll just have to deal with it */
13190     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
13191       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
13192       g_ptr_array_remove_index (qtdemux->active_streams, i);
13193       i--;
13194       continue;
13195     } else if (stream->track_id == qtdemux->chapters_track_id &&
13196         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
13197       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
13198          so that it doesn't look like a subtitle track */
13199       g_ptr_array_remove_index (qtdemux->active_streams, i);
13200       i--;
13201       continue;
13202     }
13203
13204     /* parse the initial sample for use in setting the frame rate cap */
13205     while (sample_num == 0 && sample_num < stream->n_samples) {
13206       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
13207         break;
13208       ++sample_num;
13209     }
13210   }
13211
13212   return ret;
13213 }
13214
13215 static gboolean
13216 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
13217 {
13218   return g_strcmp0 (stream->stream_id, stream_id) == 0;
13219 }
13220
13221 static gboolean
13222 qtdemux_is_streams_update (GstQTDemux * qtdemux)
13223 {
13224   gint i;
13225
13226   /* Different length, updated */
13227   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
13228     return TRUE;
13229
13230   /* streams in list are sorted in track-id order */
13231   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13232     /* Different stream-id, updated */
13233     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
13234             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
13235       return TRUE;
13236   }
13237
13238   return FALSE;
13239 }
13240
13241 static gboolean
13242 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
13243     QtDemuxStream * oldstream, QtDemuxStream * newstream)
13244 {
13245   /* Connect old stream's srcpad to new stream */
13246   newstream->pad = oldstream->pad;
13247   oldstream->pad = NULL;
13248
13249   /* unset new_stream to prevent stream-start event, unless we are EOS in which
13250    * case we need to force one through */
13251   newstream->new_stream = GST_PAD_IS_EOS (newstream->pad);
13252
13253   return gst_qtdemux_configure_stream (qtdemux, newstream);
13254 }
13255
13256 static gboolean
13257 qtdemux_update_streams (GstQTDemux * qtdemux)
13258 {
13259   gint i;
13260   g_assert (qtdemux->streams_aware);
13261
13262   /* At below, figure out which stream in active_streams has identical stream-id
13263    * with that of in old_streams. If there is matching stream-id,
13264    * corresponding newstream will not be exposed again,
13265    * but demux will reuse srcpad of matched old stream
13266    *
13267    * active_streams : newly created streams from the latest moov
13268    * old_streams : existing streams (belong to previous moov)
13269    */
13270
13271   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13272     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13273     QtDemuxStream *oldstream = NULL;
13274     guint target;
13275
13276     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
13277         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
13278
13279     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
13280             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
13281       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
13282
13283       /* null pad stream cannot be reused */
13284       if (oldstream->pad == NULL)
13285         oldstream = NULL;
13286     }
13287
13288     if (oldstream) {
13289       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
13290
13291       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
13292         return FALSE;
13293
13294       /* we don't need to preserve order of old streams */
13295       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
13296     } else {
13297       GstTagList *list;
13298
13299       /* now we have all info and can expose */
13300       list = stream->stream_tags;
13301       stream->stream_tags = NULL;
13302       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13303         return FALSE;
13304     }
13305   }
13306
13307   return TRUE;
13308 }
13309
13310 /* Must be called with expose lock */
13311 static GstFlowReturn
13312 qtdemux_expose_streams (GstQTDemux * qtdemux)
13313 {
13314   gint i;
13315
13316   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
13317
13318   if (!qtdemux_is_streams_update (qtdemux)) {
13319     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
13320     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13321       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13322       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13323       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
13324         return GST_FLOW_ERROR;
13325     }
13326
13327     g_ptr_array_set_size (qtdemux->old_streams, 0);
13328     qtdemux->need_segment = TRUE;
13329
13330     return GST_FLOW_OK;
13331   }
13332
13333   if (qtdemux->streams_aware) {
13334     if (!qtdemux_update_streams (qtdemux))
13335       return GST_FLOW_ERROR;
13336   } else {
13337     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
13338       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
13339       GstTagList *list;
13340
13341       /* now we have all info and can expose */
13342       list = stream->stream_tags;
13343       stream->stream_tags = NULL;
13344       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
13345         return GST_FLOW_ERROR;
13346
13347     }
13348   }
13349
13350   gst_qtdemux_guess_bitrate (qtdemux);
13351
13352   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
13353
13354   /* If we have still old_streams, it's no more used stream */
13355   for (i = 0; i < qtdemux->old_streams->len; i++) {
13356     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
13357
13358     if (stream->pad) {
13359       GstEvent *event;
13360
13361       event = gst_event_new_eos ();
13362       if (qtdemux->segment_seqnum)
13363         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
13364
13365       gst_pad_push_event (stream->pad, event);
13366     }
13367   }
13368
13369   g_ptr_array_set_size (qtdemux->old_streams, 0);
13370
13371   /* check if we should post a redirect in case there is a single trak
13372    * and it is a redirecting trak */
13373   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
13374       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
13375     GstMessage *m;
13376
13377     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
13378         "an external content");
13379     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
13380         gst_structure_new ("redirect",
13381             "new-location", G_TYPE_STRING,
13382             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
13383     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
13384     g_free (qtdemux->redirect_location);
13385     qtdemux->redirect_location =
13386         g_strdup (QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri);
13387   }
13388
13389   g_ptr_array_foreach (qtdemux->active_streams,
13390       (GFunc) qtdemux_do_allocation, qtdemux);
13391
13392   qtdemux->need_segment = TRUE;
13393
13394   qtdemux->exposed = TRUE;
13395   return GST_FLOW_OK;
13396 }
13397
13398 typedef struct
13399 {
13400   GstStructure *structure;      /* helper for sort function */
13401   gchar *location;
13402   guint min_req_bitrate;
13403   guint min_req_qt_version;
13404 } GstQtReference;
13405
13406 static gint
13407 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13408 {
13409   GstQtReference *ref_a = (GstQtReference *) a;
13410   GstQtReference *ref_b = (GstQtReference *) b;
13411
13412   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13413     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13414
13415   /* known bitrates go before unknown; higher bitrates go first */
13416   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13417 }
13418
13419 /* sort the redirects and post a message for the application.
13420  */
13421 static void
13422 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13423 {
13424   GstQtReference *best;
13425   GstStructure *s;
13426   GstMessage *msg;
13427   GValue list_val = { 0, };
13428   GList *l;
13429
13430   g_assert (references != NULL);
13431
13432   references = g_list_sort (references, qtdemux_redirects_sort_func);
13433
13434   best = (GstQtReference *) references->data;
13435
13436   g_value_init (&list_val, GST_TYPE_LIST);
13437
13438   for (l = references; l != NULL; l = l->next) {
13439     GstQtReference *ref = (GstQtReference *) l->data;
13440     GValue struct_val = { 0, };
13441
13442     ref->structure = gst_structure_new ("redirect",
13443         "new-location", G_TYPE_STRING, ref->location, NULL);
13444
13445     if (ref->min_req_bitrate > 0) {
13446       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13447           ref->min_req_bitrate, NULL);
13448     }
13449
13450     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13451     g_value_set_boxed (&struct_val, ref->structure);
13452     gst_value_list_append_value (&list_val, &struct_val);
13453     g_value_unset (&struct_val);
13454     /* don't free anything here yet, since we need best->structure below */
13455   }
13456
13457   g_assert (best != NULL);
13458   s = gst_structure_copy (best->structure);
13459
13460   if (g_list_length (references) > 1) {
13461     gst_structure_set_value (s, "locations", &list_val);
13462   }
13463
13464   g_value_unset (&list_val);
13465
13466   for (l = references; l != NULL; l = l->next) {
13467     GstQtReference *ref = (GstQtReference *) l->data;
13468
13469     gst_structure_free (ref->structure);
13470     g_free (ref->location);
13471     g_free (ref);
13472   }
13473   g_list_free (references);
13474
13475   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13476   g_free (qtdemux->redirect_location);
13477   qtdemux->redirect_location =
13478       g_strdup (gst_structure_get_string (s, "new-location"));
13479   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13480   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13481 }
13482
13483 /* look for redirect nodes, collect all redirect information and
13484  * process it.
13485  */
13486 static gboolean
13487 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13488 {
13489   GNode *rmra, *rmda, *rdrf;
13490
13491   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13492   if (rmra) {
13493     GList *redirects = NULL;
13494
13495     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13496     while (rmda) {
13497       GstQtReference ref = { NULL, NULL, 0, 0 };
13498       GNode *rmdr, *rmvc;
13499
13500       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13501         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13502         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13503             ref.min_req_bitrate);
13504       }
13505
13506       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13507         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13508         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13509
13510 #ifndef GST_DISABLE_GST_DEBUG
13511         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13512 #endif
13513         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13514
13515         GST_LOG_OBJECT (qtdemux,
13516             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13517             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13518             bitmask, check_type);
13519         if (package == FOURCC_qtim && check_type == 0) {
13520           ref.min_req_qt_version = version;
13521         }
13522       }
13523
13524       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13525       if (rdrf) {
13526         guint32 ref_type;
13527         guint8 *ref_data;
13528         guint ref_len;
13529
13530         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13531         if (ref_len > 20) {
13532           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13533           ref_data = (guint8 *) rdrf->data + 20;
13534           if (ref_type == FOURCC_alis) {
13535             guint record_len, record_version, fn_len;
13536
13537             if (ref_len > 70) {
13538               /* MacOSX alias record, google for alias-layout.txt */
13539               record_len = QT_UINT16 (ref_data + 4);
13540               record_version = QT_UINT16 (ref_data + 4 + 2);
13541               fn_len = QT_UINT8 (ref_data + 50);
13542               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13543                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13544               }
13545             } else {
13546               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13547                   ref_len);
13548             }
13549           } else if (ref_type == FOURCC_url_) {
13550             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13551           } else {
13552             GST_DEBUG_OBJECT (qtdemux,
13553                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13554                 GST_FOURCC_ARGS (ref_type));
13555           }
13556           if (ref.location != NULL) {
13557             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13558             redirects =
13559                 g_list_prepend (redirects, g_memdup2 (&ref, sizeof (ref)));
13560           } else {
13561             GST_WARNING_OBJECT (qtdemux,
13562                 "Failed to extract redirect location from rdrf atom");
13563           }
13564         } else {
13565           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13566         }
13567       }
13568
13569       /* look for others */
13570       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13571     }
13572
13573     if (redirects != NULL) {
13574       qtdemux_process_redirects (qtdemux, redirects);
13575     }
13576   }
13577   return TRUE;
13578 }
13579
13580 static GstTagList *
13581 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13582 {
13583   const gchar *fmt;
13584
13585   if (tags == NULL) {
13586     tags = gst_tag_list_new_empty ();
13587     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13588   }
13589
13590   if (qtdemux->major_brand == FOURCC_mjp2)
13591     fmt = "Motion JPEG 2000";
13592   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13593     fmt = "3GP";
13594   else if (qtdemux->major_brand == FOURCC_qt__)
13595     fmt = "Quicktime";
13596   else if (qtdemux->fragmented)
13597     fmt = "ISO fMP4";
13598   else
13599     fmt = "ISO MP4/M4A";
13600
13601   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13602       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13603
13604   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13605       fmt, NULL);
13606
13607   return tags;
13608 }
13609
13610 /* we have read the complete moov node now.
13611  * This function parses all of the relevant info, creates the traks and
13612  * prepares all data structures for playback
13613  */
13614 static gboolean
13615 qtdemux_parse_tree (GstQTDemux * qtdemux)
13616 {
13617   GNode *mvhd;
13618   GNode *trak;
13619   GNode *udta;
13620   GNode *mvex;
13621   GNode *pssh;
13622   guint64 creation_time;
13623   GstDateTime *datetime = NULL;
13624   gint version;
13625
13626   /* make sure we have a usable taglist */
13627   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13628
13629   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13630   if (mvhd == NULL) {
13631     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13632     return qtdemux_parse_redirects (qtdemux);
13633   }
13634
13635   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13636   if (version == 1) {
13637     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13638     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13639     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13640   } else if (version == 0) {
13641     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13642     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13643     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13644   } else {
13645     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13646     return FALSE;
13647   }
13648
13649   /* Moving qt creation time (secs since 1904) to unix time */
13650   if (creation_time != 0) {
13651     /* Try to use epoch first as it should be faster and more commonly found */
13652     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13653       gint64 now_s;
13654
13655       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13656       /* some data cleansing sanity */
13657       now_s = g_get_real_time () / G_USEC_PER_SEC;
13658       if (now_s + 24 * 3600 < creation_time) {
13659         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13660       } else {
13661         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13662       }
13663     } else {
13664       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13665       GDateTime *dt, *dt_local;
13666
13667       dt = g_date_time_add_seconds (base_dt, creation_time);
13668       dt_local = g_date_time_to_local (dt);
13669       datetime = gst_date_time_new_from_g_date_time (dt_local);
13670
13671       g_date_time_unref (base_dt);
13672       g_date_time_unref (dt);
13673     }
13674   }
13675   if (datetime) {
13676     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13677     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13678         datetime, NULL);
13679     gst_date_time_unref (datetime);
13680   }
13681
13682   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13683   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13684
13685   /* check for fragmented file and get some (default) data */
13686   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13687   if (mvex) {
13688     GNode *mehd;
13689     GstByteReader mehd_data;
13690
13691     /* let track parsing or anyone know weird stuff might happen ... */
13692     qtdemux->fragmented = TRUE;
13693
13694     /* compensate for total duration */
13695     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13696     if (mehd)
13697       qtdemux_parse_mehd (qtdemux, &mehd_data);
13698   }
13699
13700   /* Update the movie segment duration, unless it was directly given to us
13701    * by upstream. Otherwise let it as is, as we don't want to mangle the
13702    * duration provided by upstream that may come e.g. from a MPD file. */
13703   if (!qtdemux->upstream_format_is_time) {
13704     GstClockTime duration;
13705     /* set duration in the segment info */
13706     gst_qtdemux_get_duration (qtdemux, &duration);
13707     qtdemux->segment.duration = duration;
13708     /* also do not exceed duration; stop is set that way post seek anyway,
13709      * and segment activation falls back to duration,
13710      * whereas loop only checks stop, so let's align this here as well */
13711     qtdemux->segment.stop = duration;
13712   }
13713
13714   /* parse all traks */
13715   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13716   while (trak) {
13717     qtdemux_parse_trak (qtdemux, trak);
13718     /* iterate all siblings */
13719     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13720   }
13721
13722   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13723
13724   /* find tags */
13725   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13726   if (udta) {
13727     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13728   } else {
13729     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13730   }
13731
13732   /* maybe also some tags in meta box */
13733   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13734   if (udta) {
13735     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13736     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13737   } else {
13738     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13739   }
13740
13741   /* parse any protection system info */
13742   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13743   while (pssh) {
13744     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13745     qtdemux_parse_pssh (qtdemux, pssh);
13746     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13747   }
13748
13749   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13750
13751   return TRUE;
13752 }
13753
13754 /* taken from ffmpeg */
13755 static int
13756 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13757 {
13758   int count = 4;
13759   int len = 0;
13760
13761   while (count--) {
13762     int c;
13763
13764     if (ptr >= end)
13765       return -1;
13766
13767     c = *ptr++;
13768     len = (len << 7) | (c & 0x7f);
13769     if (!(c & 0x80))
13770       break;
13771   }
13772   *end_out = ptr;
13773   return len;
13774 }
13775
13776 static GList *
13777 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13778     gsize codec_data_size)
13779 {
13780   GList *list = NULL;
13781   guint8 *p = codec_data;
13782   gint i, offset, num_packets;
13783   guint *length, last;
13784
13785   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13786
13787   if (codec_data == NULL || codec_data_size == 0)
13788     goto error;
13789
13790   /* start of the stream and vorbis audio or theora video, need to
13791    * send the codec_priv data as first three packets */
13792   num_packets = p[0] + 1;
13793   GST_DEBUG_OBJECT (qtdemux,
13794       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13795       (guint) num_packets, codec_data_size);
13796
13797   /* Let's put some limits, Don't think there even is a xiph codec
13798    * with more than 3-4 headers */
13799   if (G_UNLIKELY (num_packets > 16)) {
13800     GST_WARNING_OBJECT (qtdemux,
13801         "Unlikely number of xiph headers, most likely not valid");
13802     goto error;
13803   }
13804
13805   length = g_alloca (num_packets * sizeof (guint));
13806   last = 0;
13807   offset = 1;
13808
13809   /* first packets, read length values */
13810   for (i = 0; i < num_packets - 1; i++) {
13811     length[i] = 0;
13812     while (offset < codec_data_size) {
13813       length[i] += p[offset];
13814       if (p[offset++] != 0xff)
13815         break;
13816     }
13817     last += length[i];
13818   }
13819   if (offset + last > codec_data_size)
13820     goto error;
13821
13822   /* last packet is the remaining size */
13823   length[i] = codec_data_size - offset - last;
13824
13825   for (i = 0; i < num_packets; i++) {
13826     GstBuffer *hdr;
13827
13828     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13829
13830     if (offset + length[i] > codec_data_size)
13831       goto error;
13832
13833     hdr = gst_buffer_new_memdup (p + offset, length[i]);
13834     list = g_list_append (list, hdr);
13835
13836     offset += length[i];
13837   }
13838
13839   return list;
13840
13841   /* ERRORS */
13842 error:
13843   {
13844     if (list != NULL)
13845       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13846     return NULL;
13847   }
13848
13849 }
13850
13851 /* this can change the codec originally present in @list */
13852 static void
13853 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13854     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13855 {
13856   int len = QT_UINT32 (esds->data);
13857   guint8 *ptr = esds->data;
13858   guint8 *end = ptr + len;
13859   int tag;
13860   guint8 *data_ptr = NULL;
13861   int data_len = 0;
13862   guint8 object_type_id = 0;
13863   guint8 stream_type = 0;
13864   const char *codec_name = NULL;
13865   GstCaps *caps = NULL;
13866
13867   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13868   ptr += 8;
13869   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13870   ptr += 4;
13871   while (ptr + 1 < end) {
13872     tag = QT_UINT8 (ptr);
13873     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13874     ptr++;
13875     len = read_descr_size (ptr, end, &ptr);
13876     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13877
13878     /* Check the stated amount of data is available for reading */
13879     if (len < 0 || ptr + len > end)
13880       break;
13881
13882     switch (tag) {
13883       case ES_DESCRIPTOR_TAG:
13884         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13885         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13886         ptr += 3;
13887         break;
13888       case DECODER_CONFIG_DESC_TAG:{
13889         guint max_bitrate, avg_bitrate;
13890
13891         object_type_id = QT_UINT8 (ptr);
13892         stream_type = QT_UINT8 (ptr + 1) >> 2;
13893         max_bitrate = QT_UINT32 (ptr + 5);
13894         avg_bitrate = QT_UINT32 (ptr + 9);
13895         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13896         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13897         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13898         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13899         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13900         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13901           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13902               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13903         }
13904         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13905           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13906               avg_bitrate, NULL);
13907         }
13908         ptr += 13;
13909         break;
13910       }
13911       case DECODER_SPECIFIC_INFO_TAG:
13912         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13913         if (object_type_id == 0xe0 && len == 0x40) {
13914           guint8 *data;
13915           GstStructure *s;
13916           guint32 clut[16];
13917           gint i;
13918
13919           GST_DEBUG_OBJECT (qtdemux,
13920               "Have VOBSUB palette. Creating palette event");
13921           /* move to decConfigDescr data and read palette */
13922           data = ptr;
13923           for (i = 0; i < 16; i++) {
13924             clut[i] = QT_UINT32 (data);
13925             data += 4;
13926           }
13927
13928           s = gst_structure_new ("application/x-gst-dvd", "event",
13929               G_TYPE_STRING, "dvd-spu-clut-change",
13930               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13931               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13932               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13933               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13934               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13935               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13936               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13937               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13938               NULL);
13939
13940           /* store event and trigger custom processing */
13941           stream->pending_event =
13942               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13943         } else {
13944           /* Generic codec_data handler puts it on the caps */
13945           data_ptr = ptr;
13946           data_len = len;
13947         }
13948
13949         ptr += len;
13950         break;
13951       case SL_CONFIG_DESC_TAG:
13952         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13953         ptr += 1;
13954         break;
13955       default:
13956         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13957             tag);
13958         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13959         ptr += len;
13960         break;
13961     }
13962   }
13963
13964   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13965    * in use, and should also be used to override some other parameters for some
13966    * codecs. */
13967   switch (object_type_id) {
13968     case 0x20:                 /* MPEG-4 */
13969       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13970        * profile_and_level_indication */
13971       if (data_ptr != NULL && data_len >= 5 &&
13972           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13973         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13974             data_ptr + 4, data_len - 4);
13975       }
13976       break;                    /* Nothing special needed here */
13977     case 0x21:                 /* H.264 */
13978       codec_name = "H.264 / AVC";
13979       caps = gst_caps_new_simple ("video/x-h264",
13980           "stream-format", G_TYPE_STRING, "avc",
13981           "alignment", G_TYPE_STRING, "au", NULL);
13982       break;
13983     case 0x40:                 /* AAC (any) */
13984     case 0x66:                 /* AAC Main */
13985     case 0x67:                 /* AAC LC */
13986     case 0x68:                 /* AAC SSR */
13987       /* Override channels and rate based on the codec_data, as it's often
13988        * wrong. */
13989       /* Only do so for basic setup without HE-AAC extension */
13990       if (data_ptr && data_len == 2) {
13991         guint channels, rate;
13992
13993         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13994         if (channels > 0)
13995           entry->n_channels = channels;
13996
13997         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13998         if (rate > 0)
13999           entry->rate = rate;
14000       }
14001
14002       /* Set level and profile if possible */
14003       if (data_ptr != NULL && data_len >= 2) {
14004         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14005             data_ptr, data_len);
14006       } else {
14007         const gchar *profile_str = NULL;
14008         GstBuffer *buffer;
14009         GstMapInfo map;
14010         guint8 *codec_data;
14011         gint rate_idx, profile;
14012
14013         /* No codec_data, let's invent something.
14014          * FIXME: This is wrong for SBR! */
14015
14016         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14017
14018         buffer = gst_buffer_new_and_alloc (2);
14019         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14020         codec_data = map.data;
14021
14022         rate_idx =
14023             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14024             (stream)->rate);
14025
14026         switch (object_type_id) {
14027           case 0x66:
14028             profile_str = "main";
14029             profile = 0;
14030             break;
14031           case 0x67:
14032             profile_str = "lc";
14033             profile = 1;
14034             break;
14035           case 0x68:
14036             profile_str = "ssr";
14037             profile = 2;
14038             break;
14039           default:
14040             profile = 3;
14041             break;
14042         }
14043
14044         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14045         codec_data[1] =
14046             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14047
14048         gst_buffer_unmap (buffer, &map);
14049         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14050             GST_TYPE_BUFFER, buffer, NULL);
14051         gst_buffer_unref (buffer);
14052
14053         if (profile_str) {
14054           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14055               G_TYPE_STRING, profile_str, NULL);
14056         }
14057       }
14058       break;
14059     case 0x60:                 /* MPEG-2, various profiles */
14060     case 0x61:
14061     case 0x62:
14062     case 0x63:
14063     case 0x64:
14064     case 0x65:
14065       codec_name = "MPEG-2 video";
14066       caps = gst_caps_new_simple ("video/mpeg",
14067           "mpegversion", G_TYPE_INT, 2,
14068           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14069       break;
14070     case 0x69:                 /* MPEG-2 BC audio */
14071     case 0x6B:                 /* MPEG-1 audio */
14072       caps = gst_caps_new_simple ("audio/mpeg",
14073           "mpegversion", G_TYPE_INT, 1, NULL);
14074       codec_name = "MPEG-1 audio";
14075       break;
14076     case 0x6A:                 /* MPEG-1 */
14077       codec_name = "MPEG-1 video";
14078       caps = gst_caps_new_simple ("video/mpeg",
14079           "mpegversion", G_TYPE_INT, 1,
14080           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14081       break;
14082     case 0x6C:                 /* MJPEG */
14083       caps =
14084           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14085           NULL);
14086       codec_name = "Motion-JPEG";
14087       break;
14088     case 0x6D:                 /* PNG */
14089       caps =
14090           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14091           NULL);
14092       codec_name = "PNG still images";
14093       break;
14094     case 0x6E:                 /* JPEG2000 */
14095       codec_name = "JPEG-2000";
14096       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14097       break;
14098     case 0xA4:                 /* Dirac */
14099       codec_name = "Dirac";
14100       caps = gst_caps_new_empty_simple ("video/x-dirac");
14101       break;
14102     case 0xA5:                 /* AC3 */
14103       codec_name = "AC-3 audio";
14104       caps = gst_caps_new_simple ("audio/x-ac3",
14105           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14106       break;
14107     case 0xA9:                 /* AC3 */
14108       codec_name = "DTS audio";
14109       caps = gst_caps_new_simple ("audio/x-dts",
14110           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14111       break;
14112     case 0xDD:
14113       if (stream_type == 0x05 && data_ptr) {
14114         GList *headers =
14115             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14116         if (headers) {
14117           GList *tmp;
14118           GValue arr_val = G_VALUE_INIT;
14119           GValue buf_val = G_VALUE_INIT;
14120           GstStructure *s;
14121
14122           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14123           codec_name = "Vorbis";
14124           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14125           g_value_init (&arr_val, GST_TYPE_ARRAY);
14126           g_value_init (&buf_val, GST_TYPE_BUFFER);
14127           for (tmp = headers; tmp; tmp = tmp->next) {
14128             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14129             gst_value_array_append_value (&arr_val, &buf_val);
14130           }
14131           s = gst_caps_get_structure (caps, 0);
14132           gst_structure_take_value (s, "streamheader", &arr_val);
14133           g_value_unset (&buf_val);
14134           g_list_free (headers);
14135
14136           data_ptr = NULL;
14137           data_len = 0;
14138         }
14139       }
14140       break;
14141     case 0xE1:                 /* QCELP */
14142       /* QCELP, the codec_data is a riff tag (little endian) with
14143        * 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). */
14144       caps = gst_caps_new_empty_simple ("audio/qcelp");
14145       codec_name = "QCELP";
14146       break;
14147     default:
14148       break;
14149   }
14150
14151   /* If we have a replacement caps, then change our caps for this stream */
14152   if (caps) {
14153     gst_caps_unref (entry->caps);
14154     entry->caps = caps;
14155   }
14156
14157   if (codec_name && list)
14158     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14159         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14160
14161   /* Add the codec_data attribute to caps, if we have it */
14162   if (data_ptr) {
14163     GstBuffer *buffer;
14164
14165     buffer = gst_buffer_new_and_alloc (data_len);
14166     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14167
14168     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14169     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14170
14171     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14172         buffer, NULL);
14173     gst_buffer_unref (buffer);
14174   }
14175
14176 }
14177
14178 static inline GstCaps *
14179 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14180 {
14181   GstCaps *caps;
14182   guint i;
14183   char *s, fourstr[5];
14184
14185   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14186   for (i = 0; i < 4; i++) {
14187     if (!g_ascii_isalnum (fourstr[i]))
14188       fourstr[i] = '_';
14189   }
14190   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14191   caps = gst_caps_new_empty_simple (s);
14192   g_free (s);
14193   return caps;
14194 }
14195
14196 #define _codec(name) \
14197   do { \
14198     if (codec_name) { \
14199       *codec_name = g_strdup (name); \
14200     } \
14201   } while (0)
14202
14203 static GstCaps *
14204 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14205     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14206     const guint8 * stsd_entry_data, gchar ** codec_name)
14207 {
14208   GstCaps *caps = NULL;
14209   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14210
14211   switch (fourcc) {
14212     case FOURCC_png:
14213       _codec ("PNG still images");
14214       caps = gst_caps_new_empty_simple ("image/png");
14215       break;
14216     case FOURCC_jpeg:
14217       _codec ("JPEG still images");
14218       caps =
14219           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14220           NULL);
14221       break;
14222     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14223     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14224     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14225     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14226       _codec ("Motion-JPEG");
14227       caps =
14228           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14229           NULL);
14230       break;
14231     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14232       _codec ("Motion-JPEG format B");
14233       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14234       break;
14235     case FOURCC_mjp2:
14236       _codec ("JPEG-2000");
14237       /* override to what it should be according to spec, avoid palette_data */
14238       entry->bits_per_sample = 24;
14239       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14240       break;
14241     case FOURCC_SVQ3:
14242       _codec ("Sorensen video v.3");
14243       caps = gst_caps_new_simple ("video/x-svq",
14244           "svqversion", G_TYPE_INT, 3, NULL);
14245       break;
14246     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14247     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14248       _codec ("Sorensen video v.1");
14249       caps = gst_caps_new_simple ("video/x-svq",
14250           "svqversion", G_TYPE_INT, 1, NULL);
14251       break;
14252     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14253       caps = gst_caps_new_empty_simple ("video/x-raw");
14254       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14255       _codec ("Windows Raw RGB");
14256       stream->alignment = 32;
14257       break;
14258     case FOURCC_raw_:
14259     {
14260       guint16 bps;
14261
14262       bps = QT_UINT16 (stsd_entry_data + 82);
14263       switch (bps) {
14264         case 15:
14265           format = GST_VIDEO_FORMAT_RGB15;
14266           break;
14267         case 16:
14268           format = GST_VIDEO_FORMAT_RGB16;
14269           break;
14270         case 24:
14271           format = GST_VIDEO_FORMAT_RGB;
14272           break;
14273         case 32:
14274           format = GST_VIDEO_FORMAT_ARGB;
14275           break;
14276         default:
14277           /* unknown */
14278           break;
14279       }
14280       break;
14281     }
14282     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14283       format = GST_VIDEO_FORMAT_I420;
14284       break;
14285     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14286     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14287       format = GST_VIDEO_FORMAT_I420;
14288       break;
14289     case FOURCC_2vuy:
14290     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14291       format = GST_VIDEO_FORMAT_UYVY;
14292       break;
14293     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14294       format = GST_VIDEO_FORMAT_v308;
14295       break;
14296     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14297       format = GST_VIDEO_FORMAT_v216;
14298       break;
14299     case FOURCC_v210:
14300       format = GST_VIDEO_FORMAT_v210;
14301       break;
14302     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14303       format = GST_VIDEO_FORMAT_r210;
14304       break;
14305       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14306          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14307          format = GST_VIDEO_FORMAT_v410;
14308          break;
14309        */
14310       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14311        * but different order than AYUV
14312        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14313        format = GST_VIDEO_FORMAT_v408;
14314        break;
14315        */
14316     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14317     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14318       _codec ("MPEG-1 video");
14319       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14320           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14321       break;
14322     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14323     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14324     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14325     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14326     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14327     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14328     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14329     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14330     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14331     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14332     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14333     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14334     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14335     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14336     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14337     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14338     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14339     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14340     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14341     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14342     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14343     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14344     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14345     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14346     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14347     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14348     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14349     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14350     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14351     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14352     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14353     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14354     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14355     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14356     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14357     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14358     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14359     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14360     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14361     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14362     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14363     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14364     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14365     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14366     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14367     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14368     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14369       _codec ("MPEG-2 video");
14370       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14371           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14372       break;
14373     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14374       _codec ("GIF still images");
14375       caps = gst_caps_new_empty_simple ("image/gif");
14376       break;
14377     case FOURCC_h263:
14378     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14379     case FOURCC_s263:
14380     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14381       _codec ("H.263");
14382       /* ffmpeg uses the height/width props, don't know why */
14383       caps = gst_caps_new_simple ("video/x-h263",
14384           "variant", G_TYPE_STRING, "itu", NULL);
14385       break;
14386     case FOURCC_mp4v:
14387     case FOURCC_MP4V:
14388       _codec ("MPEG-4 video");
14389       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14390           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14391       break;
14392     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14393     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14394       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14395       caps = gst_caps_new_simple ("video/x-msmpeg",
14396           "msmpegversion", G_TYPE_INT, 43, NULL);
14397       break;
14398     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14399       _codec ("DivX 3");
14400       caps = gst_caps_new_simple ("video/x-divx",
14401           "divxversion", G_TYPE_INT, 3, NULL);
14402       break;
14403     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14404     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14405       _codec ("DivX 4");
14406       caps = gst_caps_new_simple ("video/x-divx",
14407           "divxversion", G_TYPE_INT, 4, NULL);
14408       break;
14409     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14410       _codec ("DivX 5");
14411       caps = gst_caps_new_simple ("video/x-divx",
14412           "divxversion", G_TYPE_INT, 5, NULL);
14413       break;
14414
14415     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14416       _codec ("FFV1");
14417       caps = gst_caps_new_simple ("video/x-ffv",
14418           "ffvversion", G_TYPE_INT, 1, NULL);
14419       break;
14420
14421     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14422     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14423     case FOURCC_XVID:
14424     case FOURCC_xvid:
14425     case FOURCC_FMP4:
14426     case FOURCC_fmp4:
14427     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14428       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14429           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14430       _codec ("MPEG-4");
14431       break;
14432
14433     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14434       _codec ("Cinepak");
14435       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14436       break;
14437     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14438       _codec ("Apple QuickDraw");
14439       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14440       break;
14441     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14442       _codec ("Apple video");
14443       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14444       break;
14445     case FOURCC_H264:
14446     case FOURCC_avc1:
14447     case FOURCC_dva1:
14448       _codec ("H.264 / AVC");
14449       caps = gst_caps_new_simple ("video/x-h264",
14450           "stream-format", G_TYPE_STRING, "avc",
14451           "alignment", G_TYPE_STRING, "au", NULL);
14452       break;
14453     case FOURCC_avc3:
14454     case FOURCC_dvav:
14455       _codec ("H.264 / AVC");
14456       caps = gst_caps_new_simple ("video/x-h264",
14457           "stream-format", G_TYPE_STRING, "avc3",
14458           "alignment", G_TYPE_STRING, "au", NULL);
14459       break;
14460     case FOURCC_H265:
14461     case FOURCC_hvc1:
14462     case FOURCC_dvh1:
14463       _codec ("H.265 / HEVC");
14464       caps = gst_caps_new_simple ("video/x-h265",
14465           "stream-format", G_TYPE_STRING, "hvc1",
14466           "alignment", G_TYPE_STRING, "au", NULL);
14467       break;
14468     case FOURCC_hev1:
14469     case FOURCC_dvhe:
14470       _codec ("H.265 / HEVC");
14471       caps = gst_caps_new_simple ("video/x-h265",
14472           "stream-format", G_TYPE_STRING, "hev1",
14473           "alignment", G_TYPE_STRING, "au", NULL);
14474       break;
14475     case FOURCC_rle_:
14476       _codec ("Run-length encoding");
14477       caps = gst_caps_new_simple ("video/x-rle",
14478           "layout", G_TYPE_STRING, "quicktime", NULL);
14479       break;
14480     case FOURCC_WRLE:
14481       _codec ("Run-length encoding");
14482       caps = gst_caps_new_simple ("video/x-rle",
14483           "layout", G_TYPE_STRING, "microsoft", NULL);
14484       break;
14485     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14486     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14487       _codec ("Indeo Video 3");
14488       caps = gst_caps_new_simple ("video/x-indeo",
14489           "indeoversion", G_TYPE_INT, 3, NULL);
14490       break;
14491     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14492     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14493       _codec ("Intel Video 4");
14494       caps = gst_caps_new_simple ("video/x-indeo",
14495           "indeoversion", G_TYPE_INT, 4, NULL);
14496       break;
14497     case FOURCC_dvcp:
14498     case FOURCC_dvc_:
14499     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14500     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14501     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14502     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14503     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14504     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14505       _codec ("DV Video");
14506       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14507           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14508       break;
14509     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14510     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14511       _codec ("DVCPro50 Video");
14512       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14513           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14514       break;
14515     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14516     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14517       _codec ("DVCProHD Video");
14518       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14519           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14520       break;
14521     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14522       _codec ("Apple Graphics (SMC)");
14523       caps = gst_caps_new_empty_simple ("video/x-smc");
14524       break;
14525     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14526       _codec ("VP3");
14527       caps = gst_caps_new_empty_simple ("video/x-vp3");
14528       break;
14529     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14530       _codec ("VP6 Flash");
14531       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14532       break;
14533     case FOURCC_XiTh:
14534       _codec ("Theora");
14535       caps = gst_caps_new_empty_simple ("video/x-theora");
14536       /* theora uses one byte of padding in the data stream because it does not
14537        * allow 0 sized packets while theora does */
14538       entry->padding = 1;
14539       break;
14540     case FOURCC_drac:
14541       _codec ("Dirac");
14542       caps = gst_caps_new_empty_simple ("video/x-dirac");
14543       break;
14544     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14545       _codec ("TIFF still images");
14546       caps = gst_caps_new_empty_simple ("image/tiff");
14547       break;
14548     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14549       _codec ("Apple Intermediate Codec");
14550       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14551       break;
14552     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14553       _codec ("AVID DNxHD");
14554       caps = gst_caps_from_string ("video/x-dnxhd");
14555       break;
14556     case FOURCC_VP80:
14557     case FOURCC_vp08:
14558       _codec ("On2 VP8");
14559       caps = gst_caps_from_string ("video/x-vp8");
14560       break;
14561     case FOURCC_vp09:
14562       _codec ("Google VP9");
14563       caps = gst_caps_from_string ("video/x-vp9");
14564       break;
14565     case FOURCC_apcs:
14566       _codec ("Apple ProRes LT");
14567       caps =
14568           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14569           NULL);
14570       break;
14571     case FOURCC_apch:
14572       _codec ("Apple ProRes HQ");
14573       caps =
14574           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14575           NULL);
14576       break;
14577     case FOURCC_apcn:
14578       _codec ("Apple ProRes");
14579       caps =
14580           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14581           "standard", NULL);
14582       break;
14583     case FOURCC_apco:
14584       _codec ("Apple ProRes Proxy");
14585       caps =
14586           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14587           "proxy", NULL);
14588       break;
14589     case FOURCC_ap4h:
14590       _codec ("Apple ProRes 4444");
14591       caps =
14592           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14593           "4444", NULL);
14594
14595       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14596       if (entry->bits_per_sample > 0) {
14597         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14598             NULL);
14599       }
14600       break;
14601     case FOURCC_ap4x:
14602       _codec ("Apple ProRes 4444 XQ");
14603       caps =
14604           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14605           "4444xq", NULL);
14606
14607       /* 24 bits per sample = an alpha channel is coded but image is always opaque */
14608       if (entry->bits_per_sample > 0) {
14609         gst_caps_set_simple (caps, "depth", G_TYPE_INT, entry->bits_per_sample,
14610             NULL);
14611       }
14612       break;
14613     case FOURCC_cfhd:
14614       _codec ("GoPro CineForm");
14615       caps = gst_caps_from_string ("video/x-cineform");
14616       break;
14617     case FOURCC_vc_1:
14618     case FOURCC_ovc1:
14619       _codec ("VC-1");
14620       caps = gst_caps_new_simple ("video/x-wmv",
14621           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14622       break;
14623     case FOURCC_av01:
14624       _codec ("AV1");
14625       caps = gst_caps_new_empty_simple ("video/x-av1");
14626       break;
14627     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14628     default:
14629     {
14630       caps = _get_unknown_codec_name ("video", fourcc);
14631       break;
14632     }
14633   }
14634
14635   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14636     GstVideoInfo info;
14637
14638     gst_video_info_init (&info);
14639     gst_video_info_set_format (&info, format, entry->width, entry->height);
14640
14641     caps = gst_video_info_to_caps (&info);
14642     *codec_name = gst_pb_utils_get_codec_description (caps);
14643
14644     /* enable clipping for raw video streams */
14645     stream->need_clip = TRUE;
14646     stream->alignment = 32;
14647   }
14648
14649   return caps;
14650 }
14651
14652 static guint
14653 round_up_pow2 (guint n)
14654 {
14655   n = n - 1;
14656   n = n | (n >> 1);
14657   n = n | (n >> 2);
14658   n = n | (n >> 4);
14659   n = n | (n >> 8);
14660   n = n | (n >> 16);
14661   return n + 1;
14662 }
14663
14664 static GstCaps *
14665 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14666     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14667     int len, gchar ** codec_name)
14668 {
14669   GstCaps *caps;
14670   const GstStructure *s;
14671   const gchar *name;
14672   gint endian = 0;
14673   GstAudioFormat format = 0;
14674   gint depth;
14675
14676   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14677
14678   depth = entry->bytes_per_packet * 8;
14679
14680   switch (fourcc) {
14681     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14682     case FOURCC_raw_:
14683       /* 8-bit audio is unsigned */
14684       if (depth == 8)
14685         format = GST_AUDIO_FORMAT_U8;
14686       /* otherwise it's signed and big-endian just like 'twos' */
14687     case FOURCC_twos:
14688       endian = G_BIG_ENDIAN;
14689       /* fall-through */
14690     case FOURCC_sowt:
14691     {
14692       gchar *str;
14693
14694       if (!endian)
14695         endian = G_LITTLE_ENDIAN;
14696
14697       if (!format)
14698         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14699
14700       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14701       _codec (str);
14702       g_free (str);
14703
14704       caps = gst_caps_new_simple ("audio/x-raw",
14705           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14706           "layout", G_TYPE_STRING, "interleaved", NULL);
14707       stream->alignment = GST_ROUND_UP_8 (depth);
14708       stream->alignment = round_up_pow2 (stream->alignment);
14709       break;
14710     }
14711     case FOURCC_fl64:
14712       _codec ("Raw 64-bit floating-point audio");
14713       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14714        * endian later */
14715       caps = gst_caps_new_simple ("audio/x-raw",
14716           "format", G_TYPE_STRING, "F64BE",
14717           "layout", G_TYPE_STRING, "interleaved", NULL);
14718       stream->alignment = 8;
14719       break;
14720     case FOURCC_fl32:
14721       _codec ("Raw 32-bit floating-point audio");
14722       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14723        * endian later */
14724       caps = gst_caps_new_simple ("audio/x-raw",
14725           "format", G_TYPE_STRING, "F32BE",
14726           "layout", G_TYPE_STRING, "interleaved", NULL);
14727       stream->alignment = 4;
14728       break;
14729     case FOURCC_in24:
14730       _codec ("Raw 24-bit PCM audio");
14731       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14732        * endian later */
14733       caps = gst_caps_new_simple ("audio/x-raw",
14734           "format", G_TYPE_STRING, "S24BE",
14735           "layout", G_TYPE_STRING, "interleaved", NULL);
14736       stream->alignment = 4;
14737       break;
14738     case FOURCC_in32:
14739       _codec ("Raw 32-bit PCM audio");
14740       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14741        * endian later */
14742       caps = gst_caps_new_simple ("audio/x-raw",
14743           "format", G_TYPE_STRING, "S32BE",
14744           "layout", G_TYPE_STRING, "interleaved", NULL);
14745       stream->alignment = 4;
14746       break;
14747     case FOURCC_s16l:
14748       _codec ("Raw 16-bit PCM audio");
14749       caps = gst_caps_new_simple ("audio/x-raw",
14750           "format", G_TYPE_STRING, "S16LE",
14751           "layout", G_TYPE_STRING, "interleaved", NULL);
14752       stream->alignment = 2;
14753       break;
14754     case FOURCC_ulaw:
14755       _codec ("Mu-law audio");
14756       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14757       break;
14758     case FOURCC_alaw:
14759       _codec ("A-law audio");
14760       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14761       break;
14762     case 0x0200736d:
14763     case 0x6d730002:
14764       _codec ("Microsoft ADPCM");
14765       /* Microsoft ADPCM-ACM code 2 */
14766       caps = gst_caps_new_simple ("audio/x-adpcm",
14767           "layout", G_TYPE_STRING, "microsoft", NULL);
14768       break;
14769     case 0x1100736d:
14770     case 0x6d730011:
14771       _codec ("DVI/IMA ADPCM");
14772       caps = gst_caps_new_simple ("audio/x-adpcm",
14773           "layout", G_TYPE_STRING, "dvi", NULL);
14774       break;
14775     case 0x1700736d:
14776     case 0x6d730017:
14777       _codec ("DVI/Intel IMA ADPCM");
14778       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14779       caps = gst_caps_new_simple ("audio/x-adpcm",
14780           "layout", G_TYPE_STRING, "quicktime", NULL);
14781       break;
14782     case 0x5500736d:
14783     case 0x6d730055:
14784       /* MPEG layer 3, CBR only (pre QT4.1) */
14785     case FOURCC__mp3:
14786     case FOURCC_mp3_:
14787       _codec ("MPEG-1 layer 3");
14788       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14789       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14790           "mpegversion", G_TYPE_INT, 1, NULL);
14791       break;
14792     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14793       _codec ("MPEG-1 layer 2");
14794       /* MPEG layer 2 */
14795       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14796           "mpegversion", G_TYPE_INT, 1, NULL);
14797       break;
14798     case 0x20736d:
14799     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14800       _codec ("EAC-3 audio");
14801       caps = gst_caps_new_simple ("audio/x-eac3",
14802           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14803       entry->sampled = TRUE;
14804       break;
14805     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14806     case FOURCC_ac_3:
14807       _codec ("AC-3 audio");
14808       caps = gst_caps_new_simple ("audio/x-ac3",
14809           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14810       entry->sampled = TRUE;
14811       break;
14812     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14813     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14814       _codec ("DTS audio");
14815       caps = gst_caps_new_simple ("audio/x-dts",
14816           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14817       entry->sampled = TRUE;
14818       break;
14819     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14820     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14821       _codec ("DTS-HD audio");
14822       caps = gst_caps_new_simple ("audio/x-dts",
14823           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14824       entry->sampled = TRUE;
14825       break;
14826     case FOURCC_MAC3:
14827       _codec ("MACE-3");
14828       caps = gst_caps_new_simple ("audio/x-mace",
14829           "maceversion", G_TYPE_INT, 3, NULL);
14830       break;
14831     case FOURCC_MAC6:
14832       _codec ("MACE-6");
14833       caps = gst_caps_new_simple ("audio/x-mace",
14834           "maceversion", G_TYPE_INT, 6, NULL);
14835       break;
14836     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14837       /* ogg/vorbis */
14838       caps = gst_caps_new_empty_simple ("application/ogg");
14839       break;
14840     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14841       _codec ("DV audio");
14842       caps = gst_caps_new_empty_simple ("audio/x-dv");
14843       break;
14844     case FOURCC_mp4a:
14845       _codec ("MPEG-4 AAC audio");
14846       caps = gst_caps_new_simple ("audio/mpeg",
14847           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14848           "stream-format", G_TYPE_STRING, "raw", NULL);
14849       break;
14850     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14851       _codec ("QDesign Music");
14852       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14853       break;
14854     case FOURCC_QDM2:
14855       _codec ("QDesign Music v.2");
14856       /* FIXME: QDesign music version 2 (no constant) */
14857       if (FALSE && data) {
14858         caps = gst_caps_new_simple ("audio/x-qdm2",
14859             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14860             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14861             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14862       } else {
14863         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14864       }
14865       break;
14866     case FOURCC_agsm:
14867       _codec ("GSM audio");
14868       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14869       break;
14870     case FOURCC_samr:
14871       _codec ("AMR audio");
14872       caps = gst_caps_new_empty_simple ("audio/AMR");
14873       break;
14874     case FOURCC_sawb:
14875       _codec ("AMR-WB audio");
14876       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14877       break;
14878     case FOURCC_ima4:
14879       _codec ("Quicktime IMA ADPCM");
14880       caps = gst_caps_new_simple ("audio/x-adpcm",
14881           "layout", G_TYPE_STRING, "quicktime", NULL);
14882       break;
14883     case FOURCC_alac:
14884       _codec ("Apple lossless audio");
14885       caps = gst_caps_new_empty_simple ("audio/x-alac");
14886       break;
14887     case FOURCC_fLaC:
14888       _codec ("Free Lossless Audio Codec");
14889       caps = gst_caps_new_simple ("audio/x-flac",
14890           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14891       break;
14892     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14893       _codec ("QualComm PureVoice");
14894       caps = gst_caps_from_string ("audio/qcelp");
14895       break;
14896     case FOURCC_wma_:
14897     case FOURCC_owma:
14898       _codec ("WMA");
14899       caps = gst_caps_new_empty_simple ("audio/x-wma");
14900       break;
14901     case FOURCC_opus:
14902       _codec ("Opus");
14903       caps = gst_caps_new_empty_simple ("audio/x-opus");
14904       break;
14905     case FOURCC_lpcm:
14906     {
14907       guint32 flags = 0;
14908       guint32 depth = 0;
14909       guint32 width = 0;
14910       GstAudioFormat format;
14911       enum
14912       {
14913         FLAG_IS_FLOAT = 0x1,
14914         FLAG_IS_BIG_ENDIAN = 0x2,
14915         FLAG_IS_SIGNED = 0x4,
14916         FLAG_IS_PACKED = 0x8,
14917         FLAG_IS_ALIGNED_HIGH = 0x10,
14918         FLAG_IS_NON_INTERLEAVED = 0x20
14919       };
14920       _codec ("Raw LPCM audio");
14921
14922       if (data && len >= 36) {
14923         depth = QT_UINT32 (data + 24);
14924         flags = QT_UINT32 (data + 28);
14925         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14926       }
14927       if ((flags & FLAG_IS_FLOAT) == 0) {
14928         if (depth == 0)
14929           depth = 16;
14930         if (width == 0)
14931           width = 16;
14932         if ((flags & FLAG_IS_ALIGNED_HIGH))
14933           depth = width;
14934
14935         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14936             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14937             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14938         caps = gst_caps_new_simple ("audio/x-raw",
14939             "format", G_TYPE_STRING,
14940             format !=
14941             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14942             "UNKNOWN", "layout", G_TYPE_STRING,
14943             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14944             "interleaved", NULL);
14945         stream->alignment = GST_ROUND_UP_8 (depth);
14946         stream->alignment = round_up_pow2 (stream->alignment);
14947       } else {
14948         if (width == 0)
14949           width = 32;
14950         if (width == 64) {
14951           if (flags & FLAG_IS_BIG_ENDIAN)
14952             format = GST_AUDIO_FORMAT_F64BE;
14953           else
14954             format = GST_AUDIO_FORMAT_F64LE;
14955         } else {
14956           if (flags & FLAG_IS_BIG_ENDIAN)
14957             format = GST_AUDIO_FORMAT_F32BE;
14958           else
14959             format = GST_AUDIO_FORMAT_F32LE;
14960         }
14961         caps = gst_caps_new_simple ("audio/x-raw",
14962             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14963             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14964             "non-interleaved" : "interleaved", NULL);
14965         stream->alignment = width / 8;
14966       }
14967       break;
14968     }
14969     case GST_MAKE_FOURCC ('a', 'c', '-', '4'):
14970     {
14971       _codec ("AC4");
14972       caps = gst_caps_new_empty_simple ("audio/x-ac4");
14973       break;
14974     }
14975     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14976       /* ? */
14977     default:
14978     {
14979       caps = _get_unknown_codec_name ("audio", fourcc);
14980       break;
14981     }
14982   }
14983
14984   if (caps) {
14985     GstCaps *templ_caps =
14986         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14987     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14988     gst_caps_unref (caps);
14989     gst_caps_unref (templ_caps);
14990     caps = intersection;
14991   }
14992
14993   /* enable clipping for raw audio streams */
14994   s = gst_caps_get_structure (caps, 0);
14995   name = gst_structure_get_name (s);
14996   if (g_str_has_prefix (name, "audio/x-raw")) {
14997     stream->need_clip = TRUE;
14998     stream->min_buffer_size = 1024 * entry->bytes_per_frame;
14999     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15000     GST_DEBUG ("setting min/max buffer sizes to %d/%d", stream->min_buffer_size,
15001         stream->max_buffer_size);
15002   }
15003   return caps;
15004 }
15005
15006 static GstCaps *
15007 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15008     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15009     const guint8 * stsd_entry_data, gchar ** codec_name)
15010 {
15011   GstCaps *caps;
15012
15013   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15014
15015   switch (fourcc) {
15016     case FOURCC_mp4s:
15017       _codec ("DVD subtitle");
15018       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15019       stream->process_func = gst_qtdemux_process_buffer_dvd;
15020       break;
15021     case FOURCC_text:
15022       _codec ("Quicktime timed text");
15023       goto text;
15024     case FOURCC_tx3g:
15025       _codec ("3GPP timed text");
15026     text:
15027       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15028           "utf8", NULL);
15029       /* actual text piece needs to be extracted */
15030       stream->process_func = gst_qtdemux_process_buffer_text;
15031       break;
15032     case FOURCC_stpp:
15033       _codec ("XML subtitles");
15034       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15035       break;
15036     case FOURCC_wvtt:
15037     {
15038       GstBuffer *buffer;
15039       const gchar *buf = "WEBVTT\n\n";
15040
15041       _codec ("WebVTT subtitles");
15042       caps = gst_caps_new_empty_simple ("application/x-subtitle-vtt");
15043       stream->process_func = gst_qtdemux_process_buffer_wvtt;
15044
15045       /* FIXME: Parse the vttC atom and get the entire WEBVTT header */
15046       buffer = gst_buffer_new_and_alloc (8);
15047       gst_buffer_fill (buffer, 0, buf, 8);
15048       stream->buffers = g_slist_append (stream->buffers, buffer);
15049
15050       break;
15051     }
15052     case FOURCC_c608:
15053       _codec ("CEA 608 Closed Caption");
15054       caps =
15055           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15056           G_TYPE_STRING, "s334-1a", NULL);
15057       stream->process_func = gst_qtdemux_process_buffer_clcp;
15058       stream->need_split = TRUE;
15059       break;
15060     case FOURCC_c708:
15061       _codec ("CEA 708 Closed Caption");
15062       caps =
15063           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15064           G_TYPE_STRING, "cdp", NULL);
15065       stream->process_func = gst_qtdemux_process_buffer_clcp;
15066       break;
15067
15068     default:
15069     {
15070       caps = _get_unknown_codec_name ("text", fourcc);
15071       break;
15072     }
15073   }
15074   return caps;
15075 }
15076
15077 static GstCaps *
15078 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15079     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15080     const guint8 * stsd_entry_data, gchar ** codec_name)
15081 {
15082   GstCaps *caps;
15083
15084   switch (fourcc) {
15085     case FOURCC_m1v:
15086       _codec ("MPEG 1 video");
15087       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15088           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15089       break;
15090     default:
15091       caps = NULL;
15092       break;
15093   }
15094   return caps;
15095 }
15096
15097 static void
15098 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15099     const gchar * system_id)
15100 {
15101   gint i;
15102
15103   if (!qtdemux->protection_system_ids)
15104     qtdemux->protection_system_ids =
15105         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15106   /* Check whether we already have an entry for this system ID. */
15107   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15108     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15109     if (g_ascii_strcasecmp (system_id, id) == 0) {
15110       return;
15111     }
15112   }
15113   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15114   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15115           -1));
15116 }